Languages

kotlin의 고차함수 (lambda)

!쪼렙조햄 2020. 5. 26. 18:22
반응형

8장. 고차함수 : 파라미터와 반환 값으로 람다 사용

  • 고차 함수
    • 람다를 인자로 받거나 반환하는 함수
    • 고차함수를 사용해서 코드를 더 간결하게, 중복을 없애고 더 나은 추상화를 하자
  • 인라인 함수
    • 람다를 사용함에 따라 발생할 수 있는 성능상 부가비용을 없앰
    • 람다 안에서 더 유연하게 흐름을 제어할 수 있다

8.1 고차 함수 정의

  • 고차함수 : 다른 함수를 인자로 받거나 함수를 반환하는 함수
    • 코틀린에서는 람다나 함수 참조를 사요해 함수를 값으로 표현할 수 있다
    • ex) filter 함수
      • list.filter {x > 0}
      • 술어 함수를 인자로 받으므로 고차함수

8.1.1 함수 타입

val sum = {x : Int, y : Int -> x+y}
val sum : (Int, Int) -> Int = {x, y -> x+y}
// Int 파라미터 두개를 받아서 Int 값 반환하는 함수
val action = {println(42)}
val action: () -> Unit = {println(42)}
// 아무 인자도 받지 않고 리턴값이 없는(Unit) 함수
  • 함수 타입 정의는 함수 파라미터 타입 -> 함수 반환 타임 형식으로 지정
  • 함수 타입을 정의하면 lambda 안에서 parameter 타입 지정해줄 필요 없다
// 반환값이 널이 될 수 있는 경우
var canReturNull : (Int, Int) -> Int? = {x,y => null}
// 함수 자체가 널이 될 수 있는 경우
var funOrNull : ((Int, Int) -> Int)? = null
  • 349p 예제 {} 람다식 안 => 화살표의 정체 ?

8.1.2 인자로 받은 함수 호출

fun twoAndThree(operation: (Int, Int) -> Int){
    val result = operation(2,3)
    println("The result is $result")
}
twoAndThree{a,b -> a+b} // 5
twoAndThree{a,b -> a*b} // 6
  • 두 int parameter를 받아서 int 값을 반환하는 함수 타입의 파라미터를 받는 twoAndThree 함수를 정의
  • 두 int를 더하는 람다식, 두 int를 곱하는 람다식을 "operation" parameter로 넣어주어 실행

8.1.3 자바에서 코틀린 함수 타입 사용

  • 컴파일된 코드 안에서 함수 타입은 일반 인터페이스로 바뀐다
    • 함수타입 -> FunctionN 인터페이스를 구현한 객체가 된다
    • ex) Function0<R>,Funcion1<P1, R>
      • p : paramter, r : return
    • 각 인터페이스의 invoke 메소드로 함수를 실행할 수 있다
// kotlin
fun processTheAnswer(f : (Int) -> Int){
    println(f(42))
}
// java8
processTheAnswer(number -> number + 1);

// java8 이전
processTheAnswer(
    new Function1<Integer, Integer>(){
        @Override
        public Integer invoke(Integer number){
         --
        }        
    }
)
  • java8 이전의 자바에서는 필요한 FunctionN 인터페이스의 invoke 메소드를 구현해야 한다
  • 자바에서 코틀린 표준 라이브러리가 제공하는 고차함수를 호출할 수도 있다
    • 반환타입이 Unit이면 명시적으로 Unit.INSTANCE를 반환해야 한다

8.1.4 디폴트 값을 지정한 함수 타입 파라미터나 널이 될 수 있는 함수 타입 파라미터

fun <T> Collection<T>.joinToString(
    separator : String = ", ",
    transform : (T) -> String = {it.toString() }
): String{
    val result = StringBuilder(prefix)
    for (element in this){
        result.append(transform(element))
    }
}
joinToString{it.toLowerCase()}
  • joinToString 을 할때 transform 함수의 디폴트 값을 지정할 수 있다
  • joinToString을 호출할 때 다른 람다식을 넣어줄 수도 있다
  • 널이 될 수 있는 함수 타입 paramter
    • 널이 될 수 있는 함수 타입으로 함수를 받으면 그 함수를 직접 호출할 수 없다
      • NPE 가능성
fun foo(callback : (() -> Unit)?){
    if(callback != null){
        callback()
    }
}
  • 위와 같이 명시적으로 null 여부 검사하면 호출 가능

8.1.5 함수를 함수에서 반환

  • ex) 사용자가 선택한 배송 수단에 따라 배송비를 계산하는 함수를 다르게 반환

8.1.6 람다를 활용한 중복 제거

  • ex) 운영체제 별 사이트 방문 데이터 분석하기
    • os 별, path 별 하드코딩 하여 분석할 수 있다
    • 중복된 코드 부분을 람다로 만들면 중복을 제거할 수 있다
반응형