개발(Android)/kotlin syntax

[Kotlin syntax] Higher-Order Functions, Lambda Functions, Unit

shinyelee 2022. 4. 5. 21:41

[코틀린 문법] 고차함수와 람다함수와 Unit

Higher-Order Function(고차함수)

// Higher-order Function(고차함수) //

// 일반 함수를 인자나 반환값으로 사용
// 함수를 클래스에서 만들어낸 인스턴스처럼 취급하는 방법
// 함수를 파라미터로 넘겨주거나 결과값으로 반환 받을 수 있음

fun main() {

    // 일반 인자
    val res1 = sum1(3, 2)
    // 3 + 2 ->  5
    println(res1)
//    5

    // 인자에 함수 사용
    val res2 = mul1(sum1(3,3), 3)
    // (3 + 3) * 3 -> 18
    println(res2)
//    18



    // 함수의 반환값으로 함수 사용
    println("funcFunc: ${funcFunc()}")
//    funcFunc: 4



    // :: -> 고차함수로 만드는 연산자
    b(::a)
//    b가 호출한 함수 a

}



fun sum1(a: Int, b: Int) = a + b

fun mul1(a: Int, b: Int) = a * b



fun funcFunc(): Int {
    // 함수의 반환값으로 함수 사용
    return sum1(2, 2)
}



// 문자열을 받고 반환형은 없는 함수
fun a (str: String) {
    println("$str 함수 a")
}

// 함수를 자료형으로 나타내기
// Unit -> 값이 없음
fun b (function: (String)->Unit) {
    function("b가 호출한")
}

Unit

// Unit-Returning Functions(Unit을 반환하는 함수) //

// 1. 유의미한 값을 반환하지 않는 함수
// 2. Unit 타입은 (null처럼) 말 그대로 값 자체도 Unit임
// 3. 생략 가능(명시할 필요 없음)

fun main() {
    
    a("문자열을 받고 반환형은 없는")
//    문자열을 받고 반환형은 없는 함수 a
    
    printHello("Kitty!")
//    Hello Kitty

}

// 문자열을 받고 반환형은 없는 함수
fun a (str: String) {
    println("$str 함수 a")
}

// return, Unit, return Unit 생략 가능
fun printHello(name: String?)/*: Unit*/ {
    if (name != null)
        println("Hello $name")
    else
        println("Hi there!")
//     return
}

Lambda Function(람다함수)

// Lambda Function(람다 함수) //

// 고차함수 그잡채 -> 별도의 연산자 없이 변수에 담을 수 있음
// Lambda Expression(람다식), Anonymous Function(익명 함수)라고도 한다.

fun main() {

    // 이름이 없는 함수
    var result: Int

    // 일반 변수에 람다식 할당
    val multi = {x: Int, y: Int -> x * y}

    // 람다식이 할당된 변수는 함수처럼 사용 가능
    result = multi(10, 20)
    println(result)
//    200



    bb(::aa)
//    bb가 호출한 함수 aa

//    val cc: (String)->Unit = {str: String -> println("$str 람다함수 cc")}
    // 이렇게 냅다 축약해도 됨
    val cc = {str: String -> println("$str 람다함수 cc")}

    bb(cc)
//    bb가 호출한 람다함수 cc



    // 1. 여러 구문을 사용하는 람다 함수
    val d = {str: String ->
        println("$str 이런 식으로")
        println("$str 여러 구문의")
        println("$str 사용이 가능함")
    }
    val calculate: (Int, Int)->Int = {a, b ->
        println(a)
        println(b)
        a+b
    }
    // 마지막 구문인 a+b의 값을 Int로 반환함

    // 2. 파라미터가 없는 람다 함수
    // -> 실행할 구문들만 나열
    val e: ()->Unit = {println("파라미터 없음")}

    // 3. 파라미터가 하나인 람다 함수
    // -> it 사용(파라미터 이름 일일이 쓸 필요 X)
    val f: (String)->Unit = {println("$it 파라미터 하나")}

}

fun aa (str: String) {
    println("$str 함수 aa")
}

fun bb (function: (String)->Unit) {
    function("bb가 호출한")
}

// 람다 보충설명 (1)

fun main() {

    println(square(12))
//    144

    println(triangle(4))
//    8

    println(book("작별인사", 2))
//    <작별인사> 2권 주세요

    println(album("PROOF", 1))
//    <PROOF> 1장 주세요

}

// 기본형
// val 람다함수명 : (input 자료형) -> (output 자료형) = { 매개변수 -> 본문 }
val square : (Int) -> (Int) = { number -> number * number }

// 좀 더 짧게
// val 람다함수명 = { 매개변수 : 자료형 -> 본문 }
val triangle = { number : Int -> number * number / 2 }

// 기본형2
val book : (String, Int) -> String = { title : String, many : Int ->
    "<${title}> ${many}권 주세요"
}

// 좀 더 짧게2
val album = {title : String, many : Int ->
    "<${title}> ${many}장 주세요"
}
// 람다 보충설명 (2) 확장함수

fun main() {

    val a = "I love my"
    val b = "Love your"

    println(a.self())
//    I love myself:)

    println(b.self())
//    Love yourself:)

    println(extendString("you", 3000))
//    I love you 3000

}


// String.(매개변수 없음)
val self : String.() -> String = {

    // String 오브젝트 그 자체를 this로 가리킴
    this + "self:)"

}

fun extendString(who : String, much : Int) : String {

    // String.(매개변수 있음) <- this
    // 매개변수 Int를 it으로 가리킴
    val ironMan : String.(Int) -> String = { "I love ${this} ${it}" }

    return who.ironMan(much)

}
// 람다 보충설명 (3) return

fun main() {

    println(calculateGrade(74))
//    Pass

}


// input 자료형은 () 필수
// output 자료형은 () 생략 가능
val calculateGrade : (Int) -> String = {

    when(it) {
        in 0..49 -> "Fail"
        in 50..99 -> "Pass"
        100 -> "Perfect"
        else -> "Error"
        // else 필수
    }

}
// 람다 보충설명 (4) 람다를 표현하는 여러가지 방법

fun main() {

    val lambda : (Double) -> Boolean = { number : Double ->
        number == 5.4321
    }

    // invokeLambda 안에 lambda를 넣어줌
    // 5.4321 != 1.2345
    println(invokeLambda(lambda))
//    false

    // it == 1.2345
    // 1.2345 > 0.1
    println(invokeLambda{it > 0.1})
//    true

    // 원래 이런 형태인데 () 생략 가능
//    println(invokeLambda({it > 0.1}))

}

// 람다함수는 value처럼 다룰 수 있는 익명함수
// 1. 메소드의 매개변수로 넘겨줄 수 있음
// 2. 리턴값으로 쓸 수 있음

fun invokeLambda(lambda : (Double) -> Boolean) : Boolean {
    return lambda(1.2345)
}

참고

 

Functions | Kotlin

 

kotlinlang.org

반응형