Mappa mentale

training_kotlin

Programmazione funzionale

Gli esercizi sono tratti dal libro:
Programmazione funzionale in Kotlin tramite tutorial
Scritto da Massimo Carli
repo: https://github.com/kodecocodes/fpk-materials

Sintassi

FirstProgramTest

nozioni: visualizzazione schermo, funzione
PrimoProgrammaTest:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/FirstProgramTest.kt[(empty)]+

ConcatFunctionTest

nozioni: memoria, variabile, valore, oggetto, estensione della funzione
(Note: Since no French text was provided after "ExampleUnitTest:", and the instructions require translating from French to Italian with no additional context, the translation of an empty string is an empty string.)(No source text provided, so nothing to translate.)+

BirthdayMessageTestOutput

nozioni: insiemi, cicli
Introduzione a kotlin
BirthdayMessageTestOutput:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/BirthdayMessageTestOutput.kt[fonte]+

Corso di Kotlin

Tutotiel sulle collezioni in java

Il cuore delle interfacce di raccolta
Collections

Basi funzionali

Approccio dichiarativo X imperativo

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")
        })
    }
}

Esercizio 1.1

Implementare la funzione sumInRange, che somma i valori in
una List<String> in un intervallo dato. La firma è :

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") }
    )
}

Provalo e controlla la tua risposta con lahttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/DeclarativeTests.kt[solution, windows="_blank].

funzioni di ordine superiore

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() }
}

Esercizio 1.2

Implementare chrono, che accetta una funzione di tipo`() →`
Unità in input e restituisce il tempo di esecuzione. La firma è:

fun chrono(fn : () -> Unité) : Long
@Test
fun `Exercise 1_2`() {
    val waitOneSec = { sleep(ONE_SECOND) }
    chrono(waitOneSec).apply {
        println("chrono: $this")
        assertEquals(1, sign)
    }
}

Provalo e verifica la tua risposta con lahttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[solution, windows="_blank].

composizione

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))
    }

}

Funzioni pure e testabilità

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)
        }
    }
}

Gestione delle eccezioni

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
        )
    }
}

Punti chiave

  • Mentre la programmazione orientata agli oggetti significa programmare con gli oggetti,

la programmazione funzionale significa programmare con le funzioni. Suddividi un problema in più sotto-problemi, che modelli con le funzioni.

  • Le funzioni d’ordine superiore accettano altre funzioni in ingresso o restituiscono altre

funzionano come valori di ritorno. La teoria delle categorie è la teoria della composizione, e la utilizzi per comprendere come comporre le tue funzioni in un programma di lavoro Il valore di output di una funzione pura dipende solo dai suoi parametri di input, e essa non ha effetti collaterali.

  • Un effetto collaterale è qualcosa che una funzione fa al mondo esterno. Questo

può essere un registro nell’output standard o la modifica del valore di una variabile globale. La programmazione funzionale funziona per le funzioni pure, ma fornisce anche le strumenti per trasformare funzioni impure in funzioni pure Puoi rendere una funzione impura pura spostando gli effetti per renderli parte del valore di ritorno.

  • La programmazione funzionale è una questione di composizione.

La gestione degli errori è un caso tipico di effetti collaterali, e Kotlin ti fornisce gli strumenti per gestirli in modo funzionale

Approfondire Java 8: espressioni lambda e interfacce funzionali

Teoria delle categorie

La teoria matematica delle categorie

Fondamenti delle funzioni

Esercizio 2.1

Può scrivere un esempio di funzione che mappa valori distinti
il cui dominio presenta valori non distinti nell’intervallo, come f(b) e f(c) nella figura sottostante?

Provalo, poi verifica il progetto della sfida per vedere come l’hai fatto.
Troverete consigli e una spiegazione seguendo il link verso la soluzione.

Esercizio 2.2

Puoi scrivere la funzione inversa di due volte ?
Quali sono il dominio e il codominio della funzione inversa?
Dai un’occhiata al progetto della sfida e all’appendice B per la soluzione.

fun chrono(fn : () -> Unité) : Long
@Test
fun `Exercise 1_2`() {
    val waitOneSec = { sleep(ONE_SECOND) }
    chrono(waitOneSec).apply {
        println("chrono: $this")
        assertEquals(1, sign)
    }
}

Provalo e verifica la tua risposta con lahttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[soluzione, windows="_blank].

Articoli correlati