코틀린

[Youtube DiMo] 14-15강. 고차함수(함수포인터)와 람다함수/스코프함수

iseohyun 2022. 4. 29.

목차

    [14강] https://youtu.be/mvfU-7tdLWs

    [15강] https://youtu.be/QGDWWL6qA3I

     

    1. 고차함수(함수포인터)

    변수는 특정 값이 특정 메모리에 저장된 형태라면,
    함수는 특정 동작(값의 연속)이 특정 메모리에 저장된 형태이므로,
    특정 메모리를 호출한다는 입장에서 보면 함수를 가져오는 것은 당연한 개념
    문법1 (정의) :
    (인자) -> 리턴
    예) (String) -> Unit  // 문자열을 입력으로 받아 return이 없는 형태
    문법2 (함수의 주소) :
    ::함수명
    예) function
    fun main() {
        B(::A)
    }
    
    fun A(str : String) {
        println("A : $str")
    }
    
    fun B(f : (String)->Unit) {
        f("Call by B")
    }
    A : Call by B

     

    예제2)

    fun main() {
        var x : (Int, Int)->Int
        x = ::A
        B(x)
    }
    
    fun A(x : Int, y : Int) : Int {
        return x+y
    }
    
    fun B(f : (Int, Int)->Int) {
        println(f(5, 6))
    }
    11

     

     

    2. 람다함수

    함수명를 선언 후 assign(할당)하지않고, 직접 지정하는 방식
    ※ 함수의 입출력은 컴파일러가 추론
    문법
    할당받을 변수 = {인자->바디}
    fun main() {
        //var x : (Int, Int)->Int
        var x = {a:Int,b:Int->a+b}
        println(x(5,6))
    }
    11

    2-2. 람다활용 : 인자없음, 여러줄 실행

    fun main() {
        var x :()->Unit = {println("x 실행")}
        var x2 = {-> println("x2 실행")}
        
        x()
        x2()
        
        var y = { ->
            println("한줄")
            println("두줄") // return 이 없음 : kotlin.Unit
        }
        
        var y2 = {x:Int ->
            var u = x + 1
            u * u // return : Int
        }
        
        println(y())
        println(y2(2))
    }
    x 실행
    x2 실행
    한줄
    두줄
    kotlin.Unit
    9

     

    2-3. 람다활용 : 입력이 1개인 경우 <it키워드>

    fun main() {
    	var x : (String)->Unit = {println("${it}이 입력됨")}    
        x("홍길동")
    }
    홍길동이 입력됨

     

     

    3. Scope함수

    apply, run, with, also, let
      자기자신 반환 마지막구문 반환
    직접사용 apply run/with
    it 키워드 사용 also let

    3-1. apply 예제

    fun main() {
    	var a = A(1,"A")
        a.whoAmI() // 1
        
        var b = a.apply {
            i++
            str = "B"
        }
        a.whoAmI() // 2
        b.whoAmI() // 3 
    }
    
    class A(var i:Int, var str:String) {
        fun whoAmI() { println("$str : $i") }
    }
    A : 1
    B : 2
    B : 2

     

     

    3-2 run, with 예제

    fun main() {
        var a = A(1,"A")
        a.whoAmI() // 1
        
        a.run { println("$str : $i (run)")} // 2
        
        with(a) { println("$str : $i (with)")} // 3
    
    }
    
    class A(var i:Int, var str:String) {
        fun whoAmI() { println("$str : $i") }
    }
    A : 1
    A : 1 (run)
    A : 1 (with)

     

     

    3-3 run과 apply비교

    fun main() {
        var a = A(1,"A")
        var b = a.apply{i++; str="B"; "apply결과"} // a 자체가 반환
        var c = a.run{i++; str="C"; "run결과"} // 마지막 열만 반환
        
        print("b : "); print(b)
        type(b) // type은 A
        
        print("c : "); print(c)
        type(c) // type은 String
    
    }
    
    class A(var i:Int, var str:String) {
        fun whoAmI() { println("$str : $i") }
    }
    
    fun type(x : Any){
        val str = when(x){
            is String -> "(문자열)"
            is A -> "(A Class)"
            else -> "(해당 없음)"
        }
        println(str)
    }
    b : A@31cefde0(A Class)
    c : run결과(문자열)

     

     

    3-4  apply와 also의 차이점 : it 키워드를 사용 (run과 let 동일)

    fun main() {
        var i = 10
        var a = A(1).apply{i++} // 의도 : a.i를 변경, 결과 : i 변경
        
        print("Apply결과 > ")
        print("i = $i, ")
        println("a.i = ${a.i}")
        
        i = 10
    	var b = A(1).also{it.i++}
        
        print("Also 결과 > ")
        print("i = $i, ")
        println("b.i = ${b.i}")
    
    }
    
    class A(var i:Int) {}
    Apply결과 > i = 11, a.i = 1
    Also 결과 > i = 10, b.i = 2

     

    댓글