Kurs Kotlin dla programistów 3: funkcje

Te ćwiczenia są częścią kursu Kotlin dla programistów. Skorzystaj z tego kursu, jeśli będziesz wykonywać kolejno kilka ćwiczeń z programowania. W zależności od Twojej wiedzy możesz mieć dostęp do niektórych sekcji. Ten kurs jest przeznaczony dla programistów, którzy znają język zorientowany na obiekty i chcą się dowiedzieć Kotlina.

Wprowadzenie

W tym ćwiczeniu z programowania możesz utworzyć program w Kotlinie i poznać jego funkcje, w tym wartości domyślne parametrów, filtrów, lambda i funkcji kompaktowych.

Lekcje nie obejmują jednej przykładowej aplikacji, ale mają one na celu pogłębianie wiedzy. Między innymi należy jednak pamiętać o zależności od siebie. W połączeniu wiele z przykładów wykorzystuje motyw akwariowy. A jeśli chcesz zobaczyć pełne informacje o oceanarium, zapoznaj się z kursem Kotlin Bootcamp for Programmers (Ukocity) na platformie Udacity.

Co musisz wiedzieć

  • Podstawy nowoczesnego, programowanego, statycznego języka programowania
  • Jak prowadzić zajęcia z wykorzystaniem klas, metod i wyjątków w co najmniej jednym języku
  • Jak pracować z Kotlin&s REPL (Read-Eval-Print Loop) w IntelliJ IDEA
  • Podstawowe informacje o Kotlinie, w tym typy, operatory i pętle

To ćwiczenie dla programistów, którzy znają język zorientowany na obiekty i chcą dowiedzieć się więcej o Kotlinie.

Czego się nauczysz

  • Jak utworzyć program z funkcją main() i argumentami w IntelliJ IDEA
  • Jak używać wartości domyślnych i funkcji kompaktowych
  • Jak stosować filtry do list
  • Jak utworzyć podstawowe lambda i funkcje o wyższej kolejności

Jakie zadania wykonasz:

  • Skontaktuj się z REPL, aby przetestować nowy kod.
  • Pracuj z IntelliJ IDEA, aby tworzyć podstawowe programy Kotlin.

W tym zadaniu utworzysz program w Kotlin, a także poznasz funkcję main() oraz sposób przekazywania argumentów do programu z poziomu wiersza poleceń.

Możesz zapamiętać funkcję printHello() wpisaną w REPL w poprzednim ćwiczeniu z programowania:

fun printHello() {
    println ("Hello World")
}

printHello()
⇒ Hello World

Możesz zdefiniować funkcje za pomocą słowa kluczowego fun, a następnie nazwy funkcji. Tak jak w przypadku innych języków programowania, nawiasy () są argumentami funkcji (jeśli występują). Kręcone nawiasy klamrowe {} otaczają kod funkcji. Nie ma typu zwracania, ponieważ ta funkcja nie zwraca żadnych wartości.

Krok 1. Utwórz plik Kotlin

  1. Otwórz IntelliJ IDEA.
  2. Po lewej stronie w panelu Project (Projekt) w IntelliJ IDEA jest lista plików i folderów projektu. Znajdź i kliknij prawym przyciskiem myszy folder src w sekcji Hello Kotlin. (Masz już projekt Hello Kotlin z poprzedniego ćwiczenia z programowania).
  3. Wybierz New > Kotlin File / Class.
  4. W polu Rodzaj wpisz File, a następnie nadaj plikowi nazwę Hello.
  5. Kliknij OK.

W folderze src jest teraz plik o nazwie Hello.kt.

Krok 2. Dodaj kod i uruchamiaj program

  1. Podobnie jak w przypadku innych języków funkcja Kotlin main() określa punkt wejścia do wykonania. Wszystkie argumenty wiersza poleceń są przekazywane jako tablica ciągów tekstowych.

    Wpisz lub wklej ten kod w pliku Hello.kt:
fun main(args: Array<String>) {
    println("Hello, world!")
}

Tak jak we wcześniejszej funkcji printHello(), ta funkcja nie ma instrukcji return. Każda funkcja w Kotlin zwraca coś, nawet jeśli nie jest wyraźnie określony. Zatem funkcja ta main() zwraca typ kotlin.Unit, czyli w ogóle nie nadaje żadnej wartości w Kotlin.

  1. Aby uruchomić program, kliknij zielony trójkąt po lewej stronie funkcji main(). W menu wybierz Uruchom 'HelloKt'.
  2. IntelliJ IDEA kompiluje program i go uruchamia. Wyniki są wyświetlane w okienku dziennika u dołu, tak jak pokazano poniżej.

Krok 3. Przekaż argumenty funkcji main()

Ponieważ Twój program uruchamia się z poziomu IntelliJ IDEA, a nie z wiersza poleceń, musisz określić nieco argumenty w programie w inny sposób.

  1. Wybierz Run > Edit Configurations (Uruchom > Edytuj konfiguracje). Otworzy się okno Uruchamianie/debugowanie konfiguracji.
  2. Wpisz Kotlin! w polu Argumenty programu.
  3. Kliknij OK.

Krok 4. Zmień kod, aby używać szablonu ciągu znaków

Szablon ciągu znaków wstawia zmienną lub wyrażenie do ciągu tekstowego, a $ określa, że część ciągu tekstowego będzie zmienną lub wyrażeniem. Kręcone nawiasy klamrowe {} otaczają ramkę (jeśli występuje).

  1. W Hello.kt zmień komunikat powitalny, aby używać pierwszego argumentu przekazywanego do programu, args[0], zamiast "world".
fun main(args: Array<String>) {
    println("Hello, ${args[0]}")
}
  1. Uruchom program, a dane wyjściowe będą zawierać podany argument.
⇒ Hello, Kotlin!

W tym zadaniu dowiesz się, dlaczego niemal wszystkie elementy Kotlina mają wartość i dlaczego jest to przydatne.

W innych językach występują wyrażenia, czyli wiersze kodu, które nie mają wartości. W Kotlinie prawie wszystko jest wyrażeniem i ma wartość – nawet jeśli ma wartość kotlin.Unit.

  1. W polu Hello.kt wpisz kod main(), aby przypisać println() do zmiennej o nazwie isUnit i wydrukować ją. (println() nie zwraca wartości, więc zwraca kotlin.Unit).
// Will assign kotlin.Unit
val isUnit = println("This is an expression")
println(isUnit)
  1. Uruchom program. Pierwszy println() drukuje ciąg "This is an expression". Druga wartość println() drukuje wartość pierwszego wyrażenia println(), tj. kotlin.Unit.
⇒ This is an expression
kotlin.Unit
  1. Zadeklaruj atrybut val o nazwie temperature i zainicjuj go do wartości 10.
  2. Zadeklaruj inny val o nazwie isHot i przypisz wartość zwracającą instrukcję if/else do isHot, jak pokazano w poniższym kodzie. Jest to wyrażenie, więc możesz od razu użyć wartości wyrażenia if.
val temperature = 10
val isHot = if (temperature > 50) true else false
println(isHot)
⇒ false
  1. Użyj wartości wyrażenia w szablonie ciągu znaków. Dodaj kod, aby sprawdzić temperaturę, aby określić, czy ryba jest bezpieczna czy zbyt ciepła, a potem uruchom program.
val temperature = 10
val message = "The water temperature is ${ if (temperature > 50) "too warm" else "OK" }."
println(message)
⇒ The water temperature is OK.

W tym zadaniu dowiesz się więcej o funkcjach w Kotlin oraz o przydatnym wyrażeniu warunkowym when.

Krok 1. Utwórz niektóre funkcje

W tym kroku przedstawiliśmy Ci zdobytą wiedzę i utworzyliśmy różne typy funkcji. Zawartość pliku Hello.kt możesz zastąpić nowym kodem.

  1. Napisz funkcję o nazwie feedTheFish() wywołującą randomDay(), aby uzyskać losowy dzień tygodnia. Użyj szablonu ciągu znaków, aby wydrukować food, którą ryba zjedzą danego dnia. Obecnie ryby jedzą to samo jedzenie codziennie.
fun feedTheFish() {
    val day = randomDay()
    val food = "pellets"
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}
  1. Wpisz funkcję randomDay(), aby wybrać losowy dzień z tablicy i zwrócić.

Funkcja nextInt() przyjmuje liczbę całkowitą, co ogranicza liczbę od Random() do 6, by dopasować ją do tablicy week.

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
            "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}
  1. Funkcje Random() i nextInt() są zdefiniowane w java.util.*. U góry pliku dodaj odpowiedni import:
import java.util.*    // required import
  1. Uruchom program i sprawdź dane wyjściowe.
⇒ Today is Tuesday and the fish eat pellets

Krok 2. Użyj wyrażenia Kiedy

Rozszerzając kod, zmień kod tak, by wybierać różne jedzenie w różne dni, używając wyrażenia when. Instrukcja when jest podobna do switch w innych językach programowania, ale when automatycznie się kończy na końcu każdej gałęzi. Jeśli sprawdzasz wyliczenie, kod jest również pokrywany we wszystkich gałęziach.

  1. W Hello.kt dodaj funkcję o nazwie fishFood(), która przyjmuje dzień jako String i zwraca pokarm rybny na dzień jako String. Użyj strategii when(), by ryby miały codziennie określone produkty. Uruchom program kilka razy, aby sprawdzić dane wyjściowe.
fun fishFood (day : String) : String {
    var food = ""
    when (day) {
        "Monday" -> food = "flakes"
        "Tuesday" -> food = "pellets"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Saturday" -> food = "lettuce"
        "Sunday" -> food = "plankton"
    }
    return food
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)

    println ("Today is $day and the fish eat $food")
}
⇒ Today is Thursday and the fish eat granules
  1. Dodaj domyślną gałąź do wyrażenia when za pomocą else. Jeśli chcesz mieć pewność, że w programie używane są czasem wartości domyślne, usuń gałęzie Tuesday i Saturday.

    Ustawienie gałęzi domyślnej pozwala upewnić się, że wartość food jest zwracana przed zwróceniem, więc nie jest już konieczne inicjowanie. Ponieważ kod przypisuje teraz ciąg do elementu food tylko raz, możesz zadeklarować też wartość food za pomocą val zamiast var.
fun fishFood (day : String) : String {
    val food : String
    when (day) {
        "Monday" -> food = "flakes"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Sunday" -> food = "plankton"
        else -> food = "nothing"
    }
    return food
}
  1. Każde wyrażenie ma jakąś wartość, dlatego możesz uściślić jego treść. Zwraca bezpośrednio wartość wyrażenia when i eliminuje zmienną food. Wartość wyrażenia when jest wartością ostatniego wyrażenia gałęzi, która spełnia warunek.
fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

Ostateczna wersja programu wygląda mniej więcej tak:

import java.util.*    // required import

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
        "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}

fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}

W tym zadaniu poznasz domyślne wartości funkcji i metod. Przedstawiamy też kompaktowe funkcje, które zwiększają dokładność i czytelność kodu, a także ogranicza liczbę ścieżek kodu do testowania. Funkcje kompaktowe są nazywane funkcjami pojedynczych wyrażeń.

Krok 1. Utwórz wartość domyślną parametru

W Kotlin możesz przekazywać argumenty według nazwy parametru. Możesz też określić wartości domyślne parametrów: jeśli argument nie jest podany przez rozmówcę, zostanie użyta wartość domyślna. Później, kiedy piszesz metody (funkcje członków), oznacza to, że możesz uniknąć pisania wielu przeciążeń tej samej metody.

  1. W elemencie Hello.kt wpisz funkcję swim() z parametrem String o nazwie speed, który podaje szybkość ryby. Parametr speed ma wartość domyślną "fast".
fun swim(speed: String = "fast") {
   println("swimming $speed")
}
  1. Z funkcji main() wywołaj funkcję swim() na 3 sposoby. Najpierw wywołaj funkcję, używając domyślnej. Następnie wywołaj funkcję i przekaż parametr speed bez nazwy, a następnie wywołaj ją, podając nazwę parametru speed.
swim()   // uses default speed
swim("slow")   // positional argument
swim(speed="turtle-like")   // named parameter
⇒ swimming fast
swimming slow
swimming turtle-like

Krok 2. Dodaj wymagane parametry

Jeśli parametr nie ma określonej żadnej wartości domyślnej, zawsze musi być przekazywany dany argument.

  1. W polu Hello.kt napisz funkcję shouldChangeWater(), która przyjmuje 3 parametry: day, temperature i dirty. Funkcja zwraca true, jeśli woda powinna się zmienić. Dzieje się tak, gdy niedziela jest za wysoka, gdy temperatura jest zbyt wysoka lub gdy woda jest zbyt brudna. Dzień tygodnia jest wymagany, ale domyślna temperatura wynosi 22, a domyślny poziom brudu to 20.

    Użyj wyrażenia when bez argumentu, co w Kotlinie działa jako seria testów if/else if.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        temperature > 30 -> true
        dirty > 30 -> true
        day == "Sunday" ->  true
        else -> false
    }
}
  1. Zadzwoń do partnera shouldChangeWater() z firmy feedTheFish() i podaj ten dzień. Parametr day nie ma wartości domyślnej, musisz więc podać argument. Pozostałe dwa parametry shouldChangeWater() mają wartości domyślne, więc nie musisz dla nich argumentować.
fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
    println("Change water: ${shouldChangeWater(day)}")
}
=> Today is Thursday and the fish eat granules
Change water: false

Krok 3. Utwórz kompaktowe funkcje

Wyrażenie when opisane w poprzednim kroku łączy logikę w niewielką ilość kodu. Jeśli chcesz ją nieco uchwycić lub jeśli warunki do sprawdzenia są bardziej skomplikowane, możesz użyć odpowiednich zmiennych lokalnych. Kotlin obsługuje jednak kompaktowe funkcje.

W Kotlinie często występują funkcje kompaktowe, zwane też funkcjami pojedynczych wyrażeń. Gdy funkcja zwraca wyniki pojedynczego wyrażenia, możesz określić treść funkcji po symbolu =, pominąć nawiasy klamrowe {} i pominąć return.

  1. W Hello.kt dodaj kompaktowe funkcje, aby przetestować warunki.
fun isTooHot(temperature: Int) = temperature > 30

fun isDirty(dirty: Int) = dirty > 30

fun isSunday(day: String) = day == "Sunday"
  1. Zmień shouldChangeWater(), aby wywoływać nowe funkcje.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        isTooHot(temperature) -> true
        isDirty(dirty) -> true
        isSunday(day) -> true
        else  -> false
    }
}
  1. Uruchom program. Dane wyjściowe funkcji println() z użyciem shouldChangeWater() powinny być takie same jak przed przełączeniem na korzystanie z funkcji kompaktowych.

Wartości domyślne

Wartość domyślna parametru nie musi być wartością. Może to być inna funkcja, tak jak w tym przykładzie częściowym:

fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = getDirtySensorReading()): Boolean {
    ...

W tym zadaniu dowiesz się więcej o filtrach w Kotlinie. Filtry stanowią przydatny sposób na przejście do części listy na podstawie określonych warunków.

Krok 1. Utwórz filtr

  1. W Hello.kt określ listę dekoracji akwarium do najwyższego poziomu za pomocą listOf(). Możesz zastąpić zawartość pliku Hello.kt.
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
  1. Utwórz nową funkcję main() z wierszem, aby wydrukować tylko dekoracje zaczynające się od litery 'p'. Kod warunku filtra jest nawiasami klamrowymi {}, a it odwołuje się do każdego elementu, ponieważ filtr się zapętla. Jeśli wyrażenie zwróci true, element zostanie uwzględniony.
fun main() {
    println( decorations.filter {it[0] == 'p'})
}
  1. Uruchom program, a w oknie Uruchom zobaczysz te dane:
⇒ [pagoda, plastic plant]

Krok 2. Porównaj filtry chętnych i leniwych

Jeśli znasz filtry w innych językach, możesz zastanawiać się, czy filtry w Kotlin są chętne czy leniwe. Czy lista wyników jest tworzona od razu czy po uzyskaniu do niej dostępu? W Kotlinu możesz to robić w dowolny sposób. Domyślnie filter chce używać listy. Za każdym razem, gdy używasz filtra, powstaje lista.

Możesz użyć Sequence, czyli kolekcji, która pozwala wyświetlić tylko jeden element naraz, zaczynając od początku i kończąc aż do końca. Wygodne jest to, że taki interfejs API potrzebuje leniwego filtra.

  1. W aplikacji Hello.kt zmień kod, aby przypisać przefiltrowaną listę do zmiennej o nazwie eager, a następnie ją wydrukować.
fun main() {
    val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

    // eager, creates a new list
    val eager = decorations.filter { it [0] == 'p' }
    println("eager: " + eager)
  1. Pod tym kodem oceń filtr za pomocą filtra Sequence z atrybutem asSequence(). Przypisz sekwencję do zmiennej o nazwie filtered i ją wydrukuj.
   // lazy, will wait until asked to evaluate
    val filtered = decorations.asSequence().filter { it[0] == 'p' }
    println("filtered: " + filtered)

Gdy zwracasz wyniki filtra jako Sequence, zmienna filtered nie będzie zawierać nowej listy. Będzie zawierać Sequence elementów listy i wiedzę o filtrze, które chcesz zastosować do tych elementów. Za każdym razem, gdy otworzysz elementy elementu Sequence, filtr zostanie zastosowany, a wynik zostanie zwrócony.

  1. Wymuś ocenę sekwencji, konwertując ją na wartość List z toList(). Wydrukuj wynik.
    // force evaluation of the lazy list
    val newList = filtered.toList()
    println("new list: " + newList)
  1. Uruchom program i obserwuj wyniki.
⇒ eager: [pagoda, plastic plant]
filtered: kotlin.sequences.FilteringSequence@386cc1c4
new list: [pagoda, plastic plant]

Aby zobaczyć, jak działa Sequence i leniwa ocena, użyj funkcji map(). Funkcja map() wykonuje proste przekształcenie każdego elementu sekwencji.

  1. Korzystając z tej samej listy decorations, wykonaj transformację z użyciem map(), która nie powoduje żadnych działań i zwraca tylko element, który został przekazany. Dodaj println(), aby pokazywać każdorazowy dostęp do elementu, i przypisz sekwencję do zmiennej o nazwie lazyMap.
    val lazyMap = decorations.asSequence().map {
        println("access: $it")
        it
    }
  1. Drukuj lazyMap, drukuj pierwszy element lazyMap za pomocą first() i drukuj lazyMap na List.
    println("lazy: $lazyMap")
    println("-----")
    println("first: ${lazyMap.first()}")
    println("-----")
    println("all: ${lazyMap.toList()}")
  1. Uruchom program i zajrzyj na wyniki. Drukując lazyMap, drukujesz tylko odwołanie do Sequence – wewnętrzny element println() nie jest wywoływany. Drukując pierwszy element, uzyskujesz dostęp tylko do pierwszego. Konwersja parametru Sequence na wartość List uzyskuje dostęp do wszystkich elementów.
⇒ lazy: kotlin.sequences.TransformingSequence@5ba23b66
-----
access: rock
first: rock
-----
access: rock
access: pagoda
access: plastic plant
access: alligator
access: flowerpot
all: [rock, pagoda, plastic plant, alligator, flowerpot]
  1. Zanim zastosujesz filtr map, utwórz nowy: Sequence przy użyciu oryginalnego filtra. Wydrukuj wynik.
    val lazyMap2 = decorations.asSequence().filter {it[0] == 'p'}.map {
        println("access: $it")
        it
    }
    println("-----")
    println("filtered: ${ lazyMap2.toList() }")
  1. Uruchom program i sprawdź dodatkowe dane wyjściowe. Tak jak w przypadku pierwszego elementu, wewnętrzny element println() jest wywoływany tylko dla elementów, do których uzyskano dostęp.
⇒
-----
access: pagoda
access: plastic plant
filtered: [pagoda, plastic plant]

W tym zadaniu poznasz lambda i funkcje wyższego rzędu w Kotlinie.

Lambda

Oprócz tradycyjnych funkcji nazwanych Kotlin obsługuje także lambdy. lambda to wyrażenie tworzące funkcję, Zamiast jednak deklarować funkcję nazwaną, musisz zadeklarować funkcję, która nie ma nazwy. Jednym z praktycznych aspektów jest to, że wyrażenie lambda można teraz przekazywać jako dane. W innych językach lambdy są nazywane funkcjami anonimowymi, literakami funkcji lub podobnymi.

Funkcje o wyższej kolejności

Możesz utworzyć funkcję o wyższej kolejności, przekazując lambdę do innej funkcji. W poprzednim zadaniu utworzono funkcję o wyższym priorytecie – filter. Należy sprawdzić następujące wyrażenie lambda do filter jako warunku do sprawdzenia:
{it[0] == 'p'}

Podobnie map jest funkcją o wyższej kolejności, a lambda, którą do niej przekażesz, była transformacją, która została zastosowana.

Krok 1. Dowiedz się więcej o lambdach

  1. Podobnie jak funkcje nazwane, lambda mogą mieć parametry. W przypadku lambda parametry (i w razie potrzeby ich typy) znajdują się po lewej stronie funkcji nazywanej strzałką funkcyjną ->. Kod do wykonania znajduje się po prawej stronie strzałki funkcji. Gdy lambda zostanie przypisana do zmiennej, możesz ją nazywać tak jak funkcję.

    Użyj REPL (Tools > Kotlin > Kotlin REPL), wypróbuj ten kod:
var dirtyLevel = 20
val waterFilter = { dirty : Int -> dirty / 2}
println(waterFilter(dirtyLevel))
⇒ 10

W tym przykładzie lambda pobiera Int o nazwie dirty i zwraca wartość dirty / 2. Ponieważ filtr usuwa brud

  1. Składnia Kotlin&#39 dla typów funkcji jest ściśle powiązana ze składnią lambda. Użyj tej składni, aby jasno zadeklarować zmienną, która zawiera funkcję:
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }

Oto co zawiera kod:

  • Utwórz zmienną o nazwie waterFilter.
  • waterFilter może być dowolną funkcją, która przyjmuje Int i zwraca Int.
  • Przypisz lambdę do: waterFilter.
  • Lambda zwraca wartość argumentu dirty podzieloną przez 2.

Pamiętaj, że nie musisz już określać typu argumentu lambda. Typ jest obliczany na podstawie wnioskowania typu.

Krok 2. Utwórz funkcję wyższego rzędu

Do tej pory przykłady lambda wyglądają głównie jako funkcje. Prawdziwą moc lambda wykorzystuje je do tworzenia funkcji o wyższej kolejności, gdzie argumentem jednej z nich jest inna funkcja.

  1. Zapisz funkcję o wyższej kolejności. Oto podstawowy przykład: funkcja przyjmująca dwa argumenty. Pierwszy argument jest liczbą całkowitą. Drugi argument to funkcja, która przyjmuje liczbę całkowitą i zwraca liczbę całkowitą. Wypróbuj w REPL.
fun updateDirty(dirty: Int, operation: (Int) -> Int): Int {
   return operation(dirty)
}

Treść kodu wywołuje funkcję, która została przekazana jako drugi argument i przekazuje do niego pierwszy argument.

  1. Aby wywołać tę funkcję, podaj jej liczbę całkowitą i funkcję.
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
println(updateDirty(30, waterFilter))
⇒ 15

Przekazywana funkcja nie musi być lambdą. Może to być standardowa funkcja o nazwie . Aby określić argument jako funkcję standardową, użyj operatora ::. Dzięki temu Kotlin wie, że przekazujesz odwołanie do funkcji jako argument, a nie próbujesz wywołać funkcję.

  1. Spróbuj przekazać zwykłą funkcję o nazwie do updateDirty().
fun increaseDirty( start: Int ) = start + 1

println(updateDirty(15, ::increaseDirty))
⇒ 16
var dirtyLevel = 19;
dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}
println(dirtyLevel)
⇒ 42
  • Aby utworzyć plik źródłowy w Kotlin w usłudze IntelliJ IDEA, rozpocznij od projektu Kotlin.
  • Aby skompilować i uruchomić program w IntelliJ IDEA, kliknij zielony trójkąt obok funkcji main(). Dane wyjściowe pojawią się w oknie logu poniżej.
  • W narzędziu IntelliJ IDEA określ argumenty wiersza poleceń, które mają zostać przekazane do funkcji main() w sekcji Run > Edit Configurations (Uruchamianie konfiguracji &gt.).
  • Niemal wszystko w Kotlinie ma wartość. Możesz to zrobić, aby Twój kod był bardziej zwięzły, używając wartości if lub when jako wyrażenia lub wartości zwracanej.
  • Domyślne argumenty eliminują potrzebę korzystania z wielu wersji funkcji lub metody. Przykład:
    fun swim(speed: String = "fast") { ... }
  • Aby ułatwić czytanie kodu, można korzystać z funkcji kompaktowych lub jednowyrazowych. Przykład:
    fun isTooHot(temperature: Int) = temperature > 30
  • Znasz już podstawy korzystania z filtrów, które używają wyrażeń lambda. Przykład:
    val beginsWithP = decorations.filter { it [0] == 'p' }
  • Wyrażenie lambda to wyrażenie, które tworzy funkcję bez nazwy. Wyrażenia lambda są zdefiniowane między nawiasami klamrowymi {}.
  • W funkcji o wyższej kolejności przekazujesz funkcję, taką jak wyrażenie lambda, do innej funkcji jako dane. Przykład:
    dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}

W tej lekcji wiele się dzieje, zwłaszcza jeśli dopiero zaczynasz korzystać z lambda. Następna lekcja dotyczy lambda i kolejnych funkcji.

Dokumentacja Kotlin

Jeśli chcesz dowiedzieć się więcej na dowolny temat dotyczący tego kursu lub nie wiesz, co zrobić, wejdź na https://kotlinlang.org.

Samouczki Kotlin

Na stronie https://try.kotlinlang.org znajdziesz szczegółowe samouczki o nazwie Kotlin Koans, internetowe narzędzie do tłumaczenia, a także kompletny zestaw dokumentacji referencyjnej z przykładami.

Kurs Udacity

Kurs Udacity na ten temat znajdziesz na kursie Kotlin dla programistów.

IntelLIJ IDEA

Dokumentację IntelliJ IDEA znajdziesz na stronie JetBrains.

Ta sekcja zawiera listę możliwych zadań domowych dla uczniów, którzy pracują w ramach tego ćwiczenia w ramach kursu prowadzonego przez nauczyciela. To nauczyciel może wykonać te czynności:

  • W razie potrzeby przypisz zadanie domowe.
  • Poinformuj uczniów, jak przesyłać zadania domowe.
  • Oceń projekty domowe.

Nauczyciele mogą wykorzystać te sugestie tak długo, jak chcą lub chcą, i mogą przypisać dowolne zadanie domowe.

Jeśli samodzielnie wykonujesz te ćwiczenia z programowania, możesz sprawdzić swoją wiedzę w tych zadaniach domowych.

Odpowiedz na te pytania

Pytanie 1

Funkcja contains(element: String) zwraca ciąg true, jeśli ciąg element jest zawarty w ciągu znaków, który jest wywoływany. Jaki będzie wynik tego kodu?

val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

println(decorations.filter {it.contains('p')})

[pagoda, plastic, plant]

[pagoda, plastic plant]

[pagoda, plastic plant, flowerpot]

[rock, alligator]

Pytanie 2

Który z parametrów w definicji funkcji jest wymagany?
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20, numDecorations: Int = 0): Boolean {...}

numDecorations

dirty

day

temperature

Pytanie 3

Możesz przekazać zwykłą funkcję nazwaną (a nie jej wywołanie) do innej funkcji. Jaką drogą increaseDirty( start: Int ) = start + 1updateDirty(dirty: Int, operation: (Int) -> Int)?

updateDirty(15, &increaseDirty())

updateDirty(15, increaseDirty())

updateDirty(15, ("increaseDirty()"))

updateDirty(15, ::increaseDirty)

Przejdź do następnej lekcji: 4. Klasy i obiekty

Omówienie kursu, w tym linki do innych ćwiczeń z programowania, znajdziesz w artykule "Kotlin Bootcamp for Programmers: Witamy na kursie."