نقشه ذهنی

training_kotlin

برنامه‌نویسی تابعی

این execrices از کتاب گرفته شده‌اند:
برنامه‌نویسی تابعی در Kotlin با آموزش‌ها
نوشته شده توسط Massimo Carli
مخزن: https://github.com/kodecocodes/fpk-materials

سینتکس

اولین تست برنامه

مفاهیم: نمایش صفحه، عملکرد
تست برنامه اول:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/FirstProgramTest.kt[source]+

ConcatFunctionTest

مفاهیم: حافظه، متغیر، مقدار، شیء، گسترش تابع
نمونه تست واحد:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/ConcatFunctionTest.kt[منبع]+

BirthdayMessageTestOutput

مفاهیم: مجموعه‌ها، حلقات
معرفی به کاتلین
BirthdayMessageTestOutputhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/BirthdayMessageTestOutput.kt[منبع]+

دوره Kotlin

آموزش مجموعه‌ها در جاوا

قلب واجهات مجموعه
Collections

اساس‌های عملکردی

رویکرد اعلانی-اجباری X

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

تمرین ۱.۱

تابع sumInRange را پیاده‌سازی کنید که مقادیر را در
یک List<String> در یک بازه معین. امضا به صورت زیر است :

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

امتحان کنید و پاسخ خود را باhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/DeclarativeTests.kt[حل, windows="_blank].

توابع‌های رتبه بالاتر

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

تمرین 1.2

پیاده‌سازی chrono که یک تابع از نوع را می‌پذیرد`() →`
واحد در ورودی و زمان صرف شده برای اجرا آن را برمی‌گرداند. امضای آن:

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

آن را امتحان کنید و پاسخ خود را باhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[حل، windows="_blank].

ترکیب

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

}

توابع صاف و قابلیت تست

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

مدیریت استثناها

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

نقطه‌های کلیدی

  • در حالی که برنامه‌نویسی شیءگرا به این معنی است که برنامه‌نویسی با اشیاء انجام شود،

برنامه‌نویسی تابعی یعنی برنامه‌نویسی با توابع شما یک مشکل را به چندین زیرمسئله تقسیم می‌کنید، که آن‌ها را با توابع.

  • توابع از رتبه بالاتر توابع دیگر را به‌عنوان ورودی می‌پذیرند یا توابع دیگر را برمی‌گردانند

مثل مقادیر برگشتی عمل می‌کنند. نظریه‌ی دسته‌ها است نظریه‌ی ترکیب، و شما از آن برای درک استفاده می‌کنید چگونه توابع خود را در یک برنامه کاری ترکیب کنید. مقدار خروجی یک تابع پاک فقط به پارامترهای ورودی آن بستگی دارد، و آن اثرات جانبی ندارد.

  • یک اثر جانبی چیزی است که یک عملکرد در دنیای خارجی انجام می‌دهد. این

ممکن است یک لاگ در خروجی استاندارد یا تغییر مقدار یک متغیر سراسری باشد. برنامه‌نویسی عملکردی برای توابع خالص کار می‌کند، اما همچنین آن‌ها را فراهم می‌سازد ابزارها برای تبدیل توابع ناصاف به توابع صاف. می‌توانید یک تابع ناپاک را به یک تابع پاک تبدیل کنید با جابه‌جایی اثرات تا آن‌ها را پاک کنید بخش از مقدار بازگشتی

  • برنامه‌نویسی تابعی مسألهٔ ترکیب است.

مدیریت خطاها یک مورد عادی از اثرات جانبی است، و Kotlin ابزارهای لازم را برای شما فراهم می‌کند. برای مدیریت آن‌ها به صورت عملکردی.

عمیق کردن java8: عبارات lambda و واجهات عملکردی

نظریهٔ دسته‌ها

نظریه ریاضی دسته‌ها:

مبانی توابع

تمرین ۲.۱

می‌توانید یک مثال از تابعی که مقادیر متمایز را به یکدیگر نگاشت می‌کند بنویسید؟
دامنه‌ی آن چه مقادیری که متمایز نیستن در بازه، مثل f(b) و f(c) در شکل زیر؟

انجام بده، سپس پروژه چالش را برای یک راه‌حل بررسی کنید تا ببینید چقدر خوب انجام دادید.
شما مشاوره و توضیحی را با دنبال کردن لینک به …​ حل.

تمرین ۲.۲

می‌توانید معکوس تابع دو برابر را بنویسید؟
دامنه و بازه برای معکوس تابع چیست؟
ببینید پروژه چالش و ضمیمه ب برای راه‌حل.

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

آن را امتحان کنید و پاسخ خود را باhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[راه‌حل, windows="_blank].

مقالات مرتبط