프로그래머를 위한 Kotlin 부트캠프 3: 함수

이 Codelab은 프로그래머를 위한 Kotlin 부트캠프 과정의 일부입니다. Codelab을 순서대로 진행한다면 이 과정을 통해 최대한의 가치를 얻을 수 있을 것입니다. 기존 지식에 따라 일부 섹션을 훑어볼 수도 있습니다. 이 교육 과정에서는 객체 지향 언어를 알고 Kotlin을 배우고자 하는 프로그래머를 대상으로 합니다.

소개

이 Codelab에서는 Kotlin 프로그램을 만들고 매개변수, 필터, 람다, 압축 함수의 기본값을 비롯하여 Kotlin의 함수를 알아봅니다.

이 과정의 강의는 하나의 샘플 앱을 빌드하는 대신 지식을 쌓을 수 있도록 만들어졌지만 서로 종속되지 않도록 익숙해져 있는 섹션을 훑어볼 수 있습니다. 이러한 사례를 연결하는 데 도움이 되는 예시는 대부분 수족관 테마를 사용합니다. 전체 수족관 이야기를 보려면 프로그래머를 위한 Kotlin 부트캠프 Udacity 과정을 확인하세요.

기본 요건

  • 정적이고 유형화된 현대적 객체 지향 프로그래밍 언어의 기본사항
  • 하나 이상의 언어로 클래스, 메서드, 예외 처리를 프로그래밍하는 방법
  • IntelliJ IDEA에서 Kotlin's REPL (Read-Eval-Print Loop)을 사용하는 방법
  • 유형, 연산자, 루프 등 Kotlin의 기본 사항

이 Codelab은 객체 지향 언어를 알고 있고 Kotlin에 관해 자세히 알아보려는 프로그래머를 대상으로 합니다.

학습할 내용

  • IntelliJ IDEA에서 main() 함수 및 인수를 사용하여 프로그램을 만드는 방법
  • 기본값 및 압축 함수 사용 방법
  • 목록에 필터 적용 방법
  • 기본 람다 및 고차 함수를 만드는 방법

실습할 내용

  • REPL과 협력하여 코드를 사용해 봅니다.
  • IntelliJ IDEA를 사용하여 기본 Kotlin 프로그램을 만듭니다.

이 작업에서는 Kotlin 프로그램을 만들고 main() 함수를 알아보고 명령줄에서 프로그램에 인수를 전달하는 방법을 알아봅니다.

이전 Codelab에서 REPL에 입력한 printHello() 함수를 기억할 수 있습니다.

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

printHello()
⇒ Hello World

fun 키워드를 사용하여 함수를 정의한 후 함수 이름을 사용하여 함수를 정의합니다. 다른 프로그래밍 언어와 마찬가지로 괄호 ()는 함수 인수(있는 경우)에 사용됩니다. 중괄호는 함수 코드의 {} 프레임을 중괄호로 묶습니다. 이 함수에는 어떤 유형도 반환되지 않으므로 반환 유형이 없습니다.

1단계: Kotlin 파일 만들기

  1. IntelliJ IDEA를 엽니다.
  2. IntelliJ IDEA의 왼쪽에 있는 Project 창에 프로젝트 파일 및 폴더의 목록이 표시됩니다. Hello Kotlin 아래의 src 폴더를 찾아 마우스 오른쪽 버튼으로 클릭합니다. 를 클릭합니다. 이전 Codelab의 Hello Kotlin 프로젝트가 이미 있어야 합니다.
  3. New > Kotlin File / Class를 선택합니다.
  4. KindFile로 유지하고 파일 이름을 Hello로 지정합니다.
  5. 확인을 클릭합니다.

이제 src 폴더에 Hello.kt라는 파일이 있습니다.

2단계: 코드 추가 및 프로그램 실행

  1. 다른 언어와 마찬가지로 Kotlin main() 함수는 실행할 진입점을 지정합니다. 모든 명령줄 인수는 문자열 배열로 전달됩니다.

    다음 코드를 입력하거나 Hello.kt 파일에 붙여넣습니다.
fun main(args: Array<String>) {
    println("Hello, world!")
}

이전 printHello() 함수와 마찬가지로 이 함수에는 return 문이 없습니다. 명시적으로 지정되지 않은 경우에도 Kotlin의 모든 함수는 무언가를 반환합니다. 따라서 이 main() 함수와 같은 함수는 값을 표시하지 않는 Kotlin의 방식인 kotlin.Unit 유형을 반환합니다.

  1. 프로그램을 실행하려면 main() 함수 왼쪽에 있는 녹색 삼각형을 클릭합니다. 메뉴에서 Run 'HelloKt'를 선택합니다.
  2. IntelliJ IDEA는 프로그램을 컴파일하고 실행합니다. 아래와 같이 결과가 하단의 로그 창에 표시됩니다.

3단계: main()에 인수 전달

프로그램이 아니라 IntelliJ IDEA에서 프로그램을 실행하기 때문에 프로그램의 인수를 약간 다르게 지정해야 합니다.

  1. Run > Edit Configurations를 선택합니다. Run/Debug Configurations 창이 열립니다.
  2. 프로그램 인수 필드에 Kotlin!를 입력합니다.
  3. 확인을 클릭합니다.

4단계: 문자열 템플릿을 사용하도록 코드 변경

문자열 템플릿은 변수 또는 표현식을 문자열에 삽입하고 $는 문자열의 일부가 변수 또는 표현식이 되도록 지정합니다. 표현식에 중괄호 {}가 있습니다.

  1. Hello.kt에서 "world" 대신 args[0]에 전달된 첫 번째 인수를 사용하도록 인사말 메시지를 변경합니다.
fun main(args: Array<String>) {
    println("Hello, ${args[0]}")
}
  1. 프로그램을 실행하면 출력에 지정한 인수가 포함됩니다.
⇒ Hello, Kotlin!

이 작업에서는 Kotlin의 거의 모든 작업에 왜 가치가 있으며 왜 유용한지 알아봅니다.

일부 다른 언어에는 값이 없는 코드 줄인 이 있습니다. Kotlin에서 거의 모든 것은 표현식이며 값이 kotlin.Unit이더라도 값이 있습니다.

  1. Hello.kt에서 main()에 코드를 작성하여 isUnit이라는 변수에 println()를 할당하고 출력합니다. println()는 값을 반환하지 않으므로 kotlin.Unit를 반환합니다.
// Will assign kotlin.Unit
val isUnit = println("This is an expression")
println(isUnit)
  1. 프로그램을 실행합니다. 첫 번째 println()은 문자열 "This is an expression"를 출력합니다. 두 번째 println()는 첫 번째 println() 문의 값(kotlin.Unit)을 출력합니다.
⇒ This is an expression
kotlin.Unit
  1. temperature라는 val을 선언하고 10으로 초기화합니다.
  2. 다음 코드와 같이 isHot라는 또 다른 val를 선언하고 if/else 문의 반환 값을 isHot에 할당합니다. 표현식이므로 if 표현식의 값을 즉시 사용할 수 있습니다.
val temperature = 10
val isHot = if (temperature > 50) true else false
println(isHot)
⇒ false
  1. 문자열 템플릿에 표현식의 값을 사용합니다. 온도를 확인하여 물고기가 안전한지 아니면 너무 따뜻한지 판단하는 코드를 추가한 후 프로그램을 실행하세요.
val temperature = 10
val message = "The water temperature is ${ if (temperature > 50) "too warm" else "OK" }."
println(message)
⇒ The water temperature is OK.

이 작업에서는 Kotlin의 함수와 매우 유용한 when 조건식에 관해 자세히 알아봅니다.

1단계: 일부 함수 만들기

이 단계에서는 학습한 내용 중 일부를 모아 다양한 유형의 함수를 만듭니다. Hello.kt의 내용을 이 새 코드로 바꿀 수 있습니다.

  1. 임의의 요일을 가져오기 위해 randomDay()을 호출하는 feedTheFish() 함수를 작성합니다. 문자열 템플릿을 사용하여 물고기가 그날 식사할 수 있도록 food를 출력합니다. 현재 물고기는 매일 같은 음식을 먹습니다.
fun feedTheFish() {
    val day = randomDay()
    val food = "pellets"
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}
  1. randomDay() 함수를 작성하여 배열에서 임의의 날짜를 선택하고 반환합니다.

nextInt() 함수는 week 배열과 일치하도록 Random()에서 0~6까지의 숫자를 제한하는 정수 한도를 사용합니다.

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
            "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}
  1. Random()nextInt() 함수는 java.util.*에 정의되어 있습니다. 파일 상단에서 필요한 가져오기를 추가합니다.
import java.util.*    // required import
  1. 프로그램을 실행하고 출력을 확인합니다.
⇒ Today is Tuesday and the fish eat pellets

2단계: when 표현식 사용

더 이를 확장하려면 when 표현식을 사용하여 날짜별로 다른 음식을 선택하도록 코드를 변경합니다. when 문은 다른 프로그래밍 언어의 switch와 비슷하지만 각 분기가 끝날 때 자동으로 when가 중단됩니다. 또한 열거형을 검사하는 경우 코드가 모든 분기를 포괄하도록 합니다.

  1. Hello.kt에서 하루를 String로 가져와서 그날의 물고기 먹이를 String로 반환하는 fishFood()라는 함수를 추가합니다. 매일 물고기에게 특정 음식을 받도록 when()를 사용합니다. 프로그램을 여러 번 실행하여 다양한 출력을 확인합니다.
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. else를 사용하여 when 표현식에 기본 분기를 추가합니다. 테스트를 위해 프로그램에서 기본값이 사용되도록 하려면 TuesdaySaturday 분기를 삭제하세요.

    기본 분기가 있으면 food가 반환되기 전에 값을 가져오므로 더 이상 초기화할 필요가 없습니다. 이제 코드가 문자열을 food에 한 번만 할당하므로 var 대신 val를 사용하여 food를 선언할 수 있습니다.
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. 모든 표현식에 값이 있으므로 이 코드를 조금 더 간결하게 만들 수 있습니다. when 표현식의 값을 직접 반환하고 food 변수를 제거합니다. when 표현식의 값은 조건을 충족하는 분기의 마지막 표현식 값입니다.
fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

프로그램의 최종 버전은 아래의 코드와 유사합니다.

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

이 작업에서는 함수 및 메서드의 기본값에 관해 알아봅니다. 또한 코드를 간결하고 읽기 쉽게 만들 수 있으며 테스트용 코드 경로 수를 줄일 수 있는 컴팩트 함수에 관해 알아봅니다. 컴팩트 함수는 단일 표현식 함수라고도 합니다.

1단계: 매개변수의 기본값 만들기

Kotlin에서는 매개변수 이름으로 인수를 전달할 수 있습니다. 매개변수의 기본값을 지정할 수도 있습니다. 인수가 호출자에 의해 제공되지 않으면 기본값이 사용됩니다. 나중에 메서드 (구성원 함수)를 작성할 때 동일한 메서드의 오버로드 버전을 많이 작성하지 않아도 됩니다.

  1. Hello.kt에서 물고기의 속도를 출력하는 speed라는 String 매개변수를 사용하여 swim() 함수를 작성합니다. speed 매개변수의 기본값은 "fast"입니다.
fun swim(speed: String = "fast") {
   println("swimming $speed")
}
  1. main() 함수에서 세 가지 방법으로 swim() 함수를 호출합니다. 먼저 기본값을 사용하여 함수를 호출합니다. 그런 다음 함수를 호출하고 이름 없이 speed 매개변수를 전달한 후 speed 매개변수의 이름을 지정하여 함수를 호출합니다.
swim()   // uses default speed
swim("slow")   // positional argument
swim(speed="turtle-like")   // named parameter
⇒ swimming fast
swimming slow
swimming turtle-like

2단계: 필수 매개변수 추가

매개변수에 기본값이 지정되지 않으면 상응하는 인수를 항상 전달해야 합니다.

  1. Hello.kt에서 세 매개변수(day, temperature, dirty 수준)를 사용하는 shouldChangeWater() 함수를 작성합니다. 일요일마다 물을 변경해야 하는 경우 true를 반환합니다. 일요일에 온도가 너무 높거나 물이 더러우면 발생합니다. 요일은 필요하지만 기본 온도는 22, 기본 더티 수준은 20입니다.

    Kotlin에서 일련의 if/else if 검사로 작동하는 인수 없이 when 표현식을 사용합니다.
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. feedTheFish()에서 shouldChangeWater()에 전화를 걸어 하루를 제공합니다. day 매개변수에는 기본값이 없으므로 인수를 지정해야 합니다. shouldChangeWater()의 다른 두 매개변수에는 기본값이 있으므로 이러한 인수를 위해 인수를 전달할 필요가 없습니다.
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

3단계: 압축 함수 만들기

이전 단계에서 작성한 when 표현식은 많은 수의 로직을 소량의 코드로 압축합니다. 약간 압축을 풀거나 확인 조건이 더 복잡하다면 잘 알려진 로컬 변수를 사용하면 됩니다. 그러나 Kotlin은 이를 위한 압축 함수를 사용합니다.

압축 함수 또는 단일 표현식 함수는 Kotlin에서 일반적인 패턴입니다. 함수가 단일 표현식의 결과를 반환하는 경우 = 기호 뒤에 함수의 본문을 지정하고 중괄호 {}를 생략하고 return를 생략할 수 있습니다.

  1. Hello.kt에서 압축 함수를 추가하여 조건을 테스트합니다.
fun isTooHot(temperature: Int) = temperature > 30

fun isDirty(dirty: Int) = dirty > 30

fun isSunday(day: String) = day == "Sunday"
  1. shouldChangeWater()를 변경하여 새 함수를 호출합니다.
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. 프로그램을 실행합니다. shouldChangeWater()를 포함하는 println()의 출력은 압축 함수를 사용하도록 전환하기 전과 동일해야 합니다.

기본값

매개변수의 기본값은 값이 아니어도 됩니다. 다음 부분 샘플에서와 같이 다른 함수일 수도 있습니다.

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

이 작업에서는 Kotlin의 필터에 관해 알아봅니다. 필터를 사용하면 손쉽게 일부 조건에 따라 목록의 일부를 만들 수 있습니다.

1단계: 필터 만들기

  1. Hello.kt에서 listOf()를 사용하여 최상위의 수족관 장식 목록을 정의합니다. Hello.kt의 내용을 바꾸면 됩니다.
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
  1. 문자로 'p'로 시작하는 장식만 출력하는 줄을 사용하여 새 main() 함수를 만듭니다. 필터 조건의 코드는 중괄호 {}로 되어 있으며, it는 필터가 반복될 때 각 항목을 참조합니다. 표현식이 true를 반환하면 항목이 포함됩니다.
fun main() {
    println( decorations.filter {it[0] == 'p'})
}
  1. 프로그램을 실행하면 Run 창에 다음과 같은 출력이 표시됩니다.
⇒ [pagoda, plastic plant]

2단계: 즉시 및 지연 필터 비교

다른 언어로 된 필터를 잘 알고 있는 경우 Kotlin의 필터가 열려 있는지 또는 지연인지 궁금할 수 있습니다. 결과 목록이 즉시 만들어지나요? 아니면 목록에 액세스하면 되나요? Kotlin에서는 필요한 모든 방식으로 실행됩니다. 기본적으로 filter는 즉시 실행되며, 필터를 사용할 때마다 목록이 생성됩니다.

필터를 지연하려면 Sequence을 사용하면 됩니다. 컬렉션은 시작부터 끝까지 모든 항목을 한 번에 하나씩만 볼 수 있습니다. 편리하게도, 지연 필터에서 요구하는 API입니다.

  1. Hello.kt에서 필터링된 목록을 eager라는 변수에 할당하여 코드를 변경한 다음 출력합니다.
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. 이 코드 아래에 asSequence()가 있는 Sequence를 사용하여 필터를 평가합니다. filtered라는 변수에 시퀀스를 할당하고 출력합니다.
   // lazy, will wait until asked to evaluate
    val filtered = decorations.asSequence().filter { it[0] == 'p' }
    println("filtered: " + filtered)

필터 결과를 Sequence로 반환하면 filtered 변수에서 새 목록을 보유하지 않습니다. 즉, 목록 요소의 Sequence를 보유하며 이러한 요소에 적용할 필터 지식을 지닙니다. Sequence의 요소에 액세스할 때마다 필터가 적용되며 결과가 반환됩니다.

  1. 시퀀스를 강제로 평가하려면 toList()를 사용하여 List로 변환합니다. 결과를 출력합니다.
    // force evaluation of the lazy list
    val newList = filtered.toList()
    println("new list: " + newList)
  1. 프로그램을 실행하고 출력을 관찰합니다.
⇒ eager: [pagoda, plastic plant]
filtered: kotlin.sequences.FilteringSequence@386cc1c4
new list: [pagoda, plastic plant]

Sequence 및 지연 평가를 사용하여 진행 상황을 시각화하려면 map() 함수를 사용하세요. map() 함수는 시퀀스의 각 요소에 간단한 변환을 실행합니다.

  1. 위와 동일한 decorations 목록을 사용하여 map()을 사용하여 아무것도 하지 않고 변환한 요소만 전달합니다. println()를 추가하여 요소에 액세스할 때마다 표시되도록 하고 lazyMap이라는 변수에 시퀀스를 할당합니다.
    val lazyMap = decorations.asSequence().map {
        println("access: $it")
        it
    }
  1. lazyMap을 출력하고 first()를 사용하여 lazyMap의 첫 번째 요소를 출력하고 lazyMapList으로 변환하여 출력합니다.
    println("lazy: $lazyMap")
    println("-----")
    println("first: ${lazyMap.first()}")
    println("-----")
    println("all: ${lazyMap.toList()}")
  1. 프로그램을 실행하고 출력을 관찰합니다. lazyMap를 출력하면 Sequence 참조가 출력됩니다. 내부 println()는 호출되지 않습니다. 첫 번째 요소를 출력하면 첫 번째 요소만 액세스합니다. SequenceList로 변환하면 모든 요소에 액세스합니다.
⇒ 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. map를 적용하기 전에 원래 필터를 사용하여 새 Sequence를 만듭니다. 결과를 출력합니다.
    val lazyMap2 = decorations.asSequence().filter {it[0] == 'p'}.map {
        println("access: $it")
        it
    }
    println("-----")
    println("filtered: ${ lazyMap2.toList() }")
  1. 프로그램을 실행하고 추가 출력을 관찰합니다. 첫 번째 요소를 가져올 때와 마찬가지로 액세스되는 요소에만 내부 println()가 호출됩니다.
⇒
-----
access: pagoda
access: plastic plant
filtered: [pagoda, plastic plant]

이 작업에서는 Kotlin의 람다 및 고차 함수에 관해 소개합니다.

람다

Kotlin은 기존의 이름이 지정된 함수 외에도 람다를 지원합니다. 람다는 함수를 만드는 표현식입니다. 그러나 이름이 지정된 함수를 선언하는 대신 이름이 없는 함수를 선언합니다. 이 기능이 유용한 이유는 람다 표현식을 이제 데이터로 전달할 수 있다는 점입니다. 다른 언어에서 람다는 익명 함수, 함수 리터럴 또는 이와 유사한 이름이라고 합니다.

고차 함수

람다를 다른 함수에 전달하여 고차 함수를 만들 수 있습니다. 이전 작업에서는 filter라는 고차 함수를 만들었습니다. 확인할 조건으로 다음 람다 표현식을 filter에 전달했습니다.
{it[0] == 'p'}

마찬가지로 map는 고차 함수이며, 전달한 람다가 이 변환입니다.

1단계: 람다 알아보기

  1. 이름이 지정된 함수와 마찬가지로 람다에는 매개변수가 있을 수 있습니다. 람다의 경우 매개변수 (및 필요한 경우 유형)는 함수 화살표 ->의 왼쪽에 배치됩니다. 실행할 코드는 함수 화살표 오른쪽으로 이동합니다. 람다가 변수에 할당되면 함수처럼 호출할 수 있습니다.

    REPL(Tools > Kotlin > Kotlin REPL)을 사용하여 다음 코드를 사용해 보세요.
var dirtyLevel = 20
val waterFilter = { dirty : Int -> dirty / 2}
println(waterFilter(dirtyLevel))
⇒ 10

이 예에서 람다는 dirty이라는 Int를 사용하고 dirty / 2를 반환합니다. (필터링으로 먼지가 제거되기 때문).

  1. 함수 유형의 Kotlin 구문은 람다의 구문과 밀접한 관련이 있습니다. 다음 구문을 사용하여 함수가 포함된 변수를 깔끔하게 선언합니다.
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }

코드의 내용은 다음과 같습니다.

  • waterFilter 변수를 만듭니다.
  • waterFilterInt을 사용하고 Int을 반환하는 모든 함수가 될 수 있습니다.
  • 람다를 waterFilter에 할당합니다.
  • 람다는 인수 dirty의 값을 2로 나눈 값을 반환합니다.

람다 인수의 유형을 더 이상 지정하지 않아도 됩니다. 유형은 유형 추론을 통해 계산됩니다.

2단계: 고차 함수 만들기

지금까지 람다의 예는 대부분 함수와 유사합니다. 람다의 실제 성능은 람다를 사용하여 고차 함수를 만드는데, 여기서 한 함수의 인수는 다른 함수입니다.

  1. 고차 함수를 작성합니다. 기본적인 예시는 두 가지 인수를 사용하는 함수입니다. 첫 번째 인수는 정수입니다. 두 번째 인수는 정수를 가져오고 정수를 반환하는 함수입니다. REPL에서 사용해 보세요.
fun updateDirty(dirty: Int, operation: (Int) -> Int): Int {
   return operation(dirty)
}

코드 본문은 두 번째 인수로 전달된 함수를 호출하여 그 첫 번째 인수를 전달합니다.

  1. 이 함수를 호출하려면 정수 및 함수를 전달합니다.
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
println(updateDirty(30, waterFilter))
⇒ 15

전달하는 함수는 람다일 필요가 없으며, 대신 이름이 지정된 일반 함수일 수 있습니다. 인수를 일반 함수로 지정하려면 :: 연산자를 사용합니다. 이런 식으로 Kotlin은 함수 호출을 시도하지 않고 함수 참조를 인수로 전달하고 있음을 인식합니다.

  1. 일반 이름이 지정된 함수를 updateDirty()에 전달해 보세요.
fun increaseDirty( start: Int ) = start + 1

println(updateDirty(15, ::increaseDirty))
⇒ 16
var dirtyLevel = 19;
dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}
println(dirtyLevel)
⇒ 42
  • IntelliJ IDEA에서 Kotlin 소스 파일을 만들려면 Kotlin 프로젝트를 시작합니다.
  • IntelliJ IDEA에서 프로그램을 컴파일하고 실행하려면 main() 함수 옆의 녹색 삼각형을 클릭합니다. 아래의 로그 창에 출력이 표시됩니다.
  • IntelliJ IDEA에서 Run > Edit Configurationsmain() 함수에 전달할 명령줄 인수를 지정합니다.
  • Kotlin의 거의 모든 것에는 값이 있습니다. 이 사실을 이용하여 if 또는 when의 값을 표현식 또는 반환 값으로 사용하여 코드를 더 간결하게 만들 수 있습니다.
  • 기본 인수를 사용하면 함수나 메서드의 여러 버전이 필요하지 않습니다. 예를 들면 다음과 같습니다.
    fun swim(speed: String = "fast") { ... }
  • 압축 함수 또는 단일 표현식 함수를 사용하면 코드를 더 쉽게 읽을 수 있습니다. 예를 들면 다음과 같습니다.
    fun isTooHot(temperature: Int) = temperature > 30
  • 람다 표현식을 사용하는 필터에 대한 몇 가지 기본사항을 배웠습니다. 예를 들면 다음과 같습니다.
    val beginsWithP = decorations.filter { it [0] == 'p' }
  • 람다 표현식은 이름이 지정되지 않은 함수를 만드는 표현식입니다. 람다 표현식은 중괄호 {}로 정의됩니다.
  • 고차 함수에서 람다 표현식과 같은 함수를 다른 함수에 데이터로 전달합니다. 예:
    dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}

이 단원에서는 특히 람다를 처음 접하는 경우 많은 것을 배울 수 있습니다. 이후 과정에서는 람다 및 고차 함수를 다시 살펴봅니다.

Kotlin 문서

이 과정의 주제에 관해 자세히 알아보거나 도움이 필요한 경우 https://kotlinlang.org에서 시작하면 됩니다.

Kotlin 튜토리얼

https://try.kotlinlang.org 웹사이트에는 웹 기반 인터프리터라는 Kotlin Koans라는 풍부한 튜토리얼과 예시를 제공하는 완전한 참조 문서가 있습니다.

Udacity 과정

이 주제에 관한 Udacity 과정을 보려면 프로그래머를 위한 Kotlin 부트캠프를 참고하세요.

IntelliJ IDEA

IntelliJ IDEA에 관한 문서는 JetBrains 웹사이트에서 찾을 수 있습니다.

이 섹션에는 강사가 진행하는 과정의 일부로 이 Codelab을 통해 작업하는 학생들의 숙제 과제가 나와 있습니다. 강사는 다음을 처리합니다.

  • 필요한 경우 과제를 할당합니다.
  • 학생에게 과제 과제를 제출하는 방법을 알려주세요.
  • 과제 과제를 채점합니다.

강사는 이러한 추천을 원하는 만큼 사용할 수 있으며 다른 적절한 숙제를 할당해도 좋습니다.

이 Codelab을 직접 학습하고 있다면 언제든지 숙제를 통해 지식을 확인해 보세요.

답변

질문 1

호출된 문자열에 element 문자열이 포함된 경우 contains(element: String) 함수는 true를 반환합니다. 다음 코드는 어떻게 출력되나요?

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]

질문 2

다음 함수 정의에서 필수 매개변수는 무엇인가요?
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20, numDecorations: Int = 0): Boolean {...}

numDecorations

dirty

day

temperature

질문 3

호출된 결과가 아닌 일반 이름이 지정된 함수를 다른 함수에 전달할 수 있습니다. increaseDirty( start: Int ) = start + 1updateDirty(dirty: Int, operation: (Int) -> Int)에 어떻게 전달할까요?

updateDirty(15, &increaseDirty())

updateDirty(15, increaseDirty())

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

updateDirty(15, ::increaseDirty)

다음 강의로 진행합니다. 4. 클래스 및 객체

다른 Codelab으로 연결되는 링크를 포함한 과정 개요는 "프로그래머를 위한 Kotlin 부트캠프: 교육 과정에 오신 것을 환영합니다.를 참고하세요.