코틀린에서의 Functional Programming

김종완·2022년 6월 7일
0

코틀린 문법 학습

목록 보기
6/6

코틀린에서의 Collection


가변(Mutable) 컬렉션 : 컬렉션에 element를 추가, 삭제할 수 있다.
불변 컬렉션: 컬렉션에 element를 추가, 삭제할 수 없다. 기존에 존재하는 field 값은 변경 가능하다.

코틀린에서 배열 사용법

fun main() {
    // array 생성 방법
    val array = arrayOf(100, 200)

    // 배열에 인덱스로 접근하는 방법
    for (i in array.indices){
        println("${i} ${array[i]}")
    }

    // 배열에 인덱스와 값에 한번에 접근하는 방법
    for ((idx, value) in array.withIndex()) {
        println("$idx $value")
    }
}

코틀린에서 리스트 사용법

    val numbers = listOf<Int>(100, 200)
    val empty = emptyList<Int>()

    // 가변 : Mutable
    // 가변(Mutable) 리스트를 만들고 싶다면?!!
    // val Mutable_numbers = mutableListOf(100, 200)
    // numbers.add(300)

    // 집합 선언 방법 val numbers = setOf(100, 200)
    // 가변 집합 val numbers = mutableSetOf(100, 200)

    // 추론 가능하기에 에러 x
    printNumbers(emptyList())

    println(numbers[0])

    for(number in numbers){
        println(number)
    }

    for ((idx, value) in numbers.withIndex()) {
        println("${idx} ${value}")
    }

코틀린에서 맵 사용법

fun main(){

    val oldMap = mutableMapOf<Int, String>()
    oldMap[1] = "MONDAY"
    oldMap[2] = "TUESDAY"

    // 불변맵 초기화 방법
    // mapOf(1 to "MONDAY", 2 to "TUESDAY")

    for (key in oldMap.keys) {
        println(key)
        println(oldMap[key])
    }

    for ((key, vlaue) in oldMap.entries){

    }
}

리스트 사용시 주의할 점

List<Int?> : 리스트에 null이 들어갈 수 있지만, 리스트는 절대 null이 아님

List? : 리스트에는 null이 들어갈 수 없지만, 리스트는 null일 수 있음

List<Int?>? : 리스트에 null이 들어갈 수도 있고, 리스트가 null일 수도 있음

  • 코틀린에서는 컬렉션을 만들 때도 불변/가변을 지정해야 한다.
  • List, Set, Map 에 대한 사용법이 변경, 확장되었다.
  • Java와 Kotlin 코드를 섞어 컬렉션을 사용할 때에는 주의해야 한다.
    • Java에서 Kotlin 컬렉션을 가져갈 때는 불변 컬렉션을 수정할 수도 있고, non-nullable 컬렉션에 null을 넣을 수도 있다.
    • Kotlin에서 Java 컬렉션을 가져갈 때는 플랫폼타입을 주의해야 한다.

코틀린에서 다양한 함수를 다루는 방법


  • Java 코드가 있는 상황에서, Kotlin 코드로 추가 기능 개발을 하기 위해 확장함수와 확장프로퍼티가 등장했다.
  • 확장 함수
    fun 확장하려는클래스.함수이름(파라미터): 리턴타입 {
    // this를 이용해 실제 클래스 안의 값에 접근
    }
    • 여기서 this는 수신객체
    • 여기서 확장하려는 클래스는 수신객체 타입
  • 확장함수는 원본 클래스의 private, protected 멤버 접근이 안된다
  • 멤버함수, 확장함수 중 멤버함수에 우선권이 있다
  • 확장함수는 현재 타입을 기준으로 호출된다
  • Java에서는 static 함수를 쓰는것처럼 Kotlin의 확장함수를 쓸 수 있다.
  • 함수 호출 방식을 바꿔주는 infix 함수가 존재한다.
    • 호출시 3.add(4)를 3 add2 4 이런 식으로 호출 가능
  • 함수를 복사-붙여넣기 하는 inline 함수가 존재한다.
  • Kotlin에서는 함수 안에 함수를 선언할 수 있고, 지역 함수라고 부른다.

코틀린에서 람다를 다루는 방법

예제를 통한 설명

class Fruit (val name: String, val price: Int)

fun main() {
  val fruits = listOf(
      Fruit("사과", 1_000),
      Fruit("사과", 1_200),
      Fruit("사과", 1_200),
      Fruit("사과", 1_500),
      Fruit("바나나", 3_000),
      Fruit("바나나", 3_200),
      Fruit("바나나", 2_500),
      Fruit("수박", 10_000),
  )

  // 람다란 익명 함수

  // 함수의 타입: (파라미터 타입...) -> 반환 타입
  val isApple: (Fruit) -> Boolean = fun(fruit: Fruit): Boolean {
      return fruit.name == "사과"
  }

  val isApple2: (Fruit) -> Boolean = {fruit: Fruit -> fruit.name == "사과"}

  // 람다를 직접 호출하는 방법 1
  println(isApple(fruits[0]))

  // 람다를 직접 호출하는 방법 2
  println(isApple.invoke(fruits[0]))

  // 마지막 파라미터가 함수인 경우, 소괄호 밖에 람다 사용 가능하다.(추천)
  println(filterFruits(fruits) {fruit -> fruit.name == "사과"})

  // 파라미터가 하나일 경우 아래와 같이 it을 사용할 수 있다.(비추)
  println(filterFruits(fruits) {it.name == "사과"})

  // tip : 람다를 여러줄 작성할 수 있고, 마지막 줄의 결과가 람다의 반환값이다.
}

// 코틀린에서는 함수를 파라미터로 받을 수 있다.
// filter: (Fruit) -> Boolean 의미는 Fruit를 파라미터로 밭고 Boolean 타입을 리턴하는 함수를 변수로 받겠다고 명시한 것이다.
private fun filterFruits(
  fruits: List<Fruit>, filter: (Fruit) -> Boolean
): List<Fruit>{
  val results = mutableListOf<Fruit>()
  for (fruit in fruits) {
      if (filter(fruit)) {
          results.add(fruit)
      }
  }
  return results
}
  • 함수는 Java에서 2급 시민이지만, 코틀린에서는 1급 시민이다.
    • 때문에, 함수 자체를 변수에 넣을 수도 있고 파라미터로 전달할 수도 있다.
  • 코틀린에서 함수 타입은 (파라미터 타입, ...) -> 반환타입 이었다.
  • 코틀린에서 람다는 두 가지 방법으로 만들 수 있고, {} 방법이 더 많이 사용된다.
  • 함수를 호출하며, 마지막 파라미터인 람다를 쓸 때는 소괄호 밖으로 람다를 뺄 수 있다.
  • 람다의 마지막 expression 결과는 람다의 반환 값이다.
  • 코틀린에서는 Closure를 사용하여 non-final 변수도 람다에서 사용할 수 있다.
profile
개발에 재미를 느끼며 꾸준히 성장하는 개발자 김종완 입니다.

0개의 댓글