본문 바로가기
프로그래밍 놀이터/Kotlin

[도서 정리] Android Development with Kotlin - Playing with Functions

by 돼지왕왕돼지 2018. 12. 12.

Android Development with Kotlin - Playing with Functions



이 정리글은 Kotlin in Action 책을 보고 실무에 Kotlin 을 사용하던 사람이 몰랐던 내용이나 remind 하고 싶은 내용을 위주로 정리한 글입니다.

제대로 내용을 파악하시려면 책을 구매해서 읽어보세욤~


@file, @file:jvmmultifileclass, @file:JvmName, android with kotlin, argument vs parameter, function vs method, last operation, nothing 은 모든 type 의 subtype, playing with functions, recursive stackoverflow, tail recursive function, tailrec, tailrec condition, top level function compile, top level function import, Unit, unit singleton, vararg


-

Function 과 Method 를 구분하는 논리..

Function 은 이름을 가진 Code 조각.

Method 는 class 와 연관되어진 function. member function 을 method 라 부른다.


논란의 여지는 있는데 Java 에는 Method 만 있다는 의견이 많다.

일각에서는 static function 은 function 이라고 이야기하기도 한다.


Kotlin 에서의 function 은 object 와 연관되어 있지 않은 function 을 이야기한다.



-

Argument 과 Parameter 를 구분하는 논리.

보통은 그 둘을 구분 없이 사용하지만 엄밀히 구분하자면...

아래의 코드에서 msg 는 parameter 이고, “testString” 이 argument 이다.

fun print(msg:String){
    ...
}
print(“testString”)



-

val p = printSum(1, 2) println( p is Unit) // true


Unit 은 singleton 이다.



-

vararg 로 전달되는 녀석은 Array<T> 형태를 갖는다.

역시나 최적화를 위해 T 가 Int 인 경우 최적화된 형태인 IntArray 가 전달된다.



-

Tail-recursive functions 는 처음 본 개념이다.

아래 코드 형태를 tail-recursive function 이라 부른다.

꼬리쪽에서 recursive function call 을 하는 경우를 말한다.

fun getState(state:State, n:Int): State =
    if(n <=0) state
    else getState(nextState(state), n-1)

위와 같은 recursive function call 을 사용하는 경우에 n 이 높으면 StackOverflowError 가 날 수 있다.


이를 해결하는 방법은 recursive 를 푸는 것이다.

fun getState(state: State, n: Int) : State {
    var state = state
    for (i in 1..n){
        state = state.nextState()
    }
    return state
}

그러나 이렇게 푸는 방법은 조금 어려울 수 있다.

이를 Kotlin 에서 잘 도와준다.


“tailrec” modifier 를 써주면 알아서 StackOverflowError 가 나지 않게 최적화를 잘 해준다.

tailrec fun getState(state:State, n:Int): State =
    if(n <=0) state
    else getState(nextState(state), n-1)


tailrec 을 붙인 compile 된 코드를 decompile 하면 아래와 같은 코드를 얻는다

public static final State getState(@NotNull State state, int n){
    while(true) { 
        if(n <= 0) { 
            return state; 
        } 
        state = state.nextState(); 
        n = n - 1; 
    } 
}


-

tailrec 를 붙일 수 있는 조건은 다음과 같다.

    recursive call 이 last operation 으로 이루어져야 한다.

    try/catch/finally block 이 아닌 곳에서 불러야 한다.

    kotlin 에서만 사용 가능하다.



-

top-level function 으로 정의된 경우 전체에서 local function 부르듯이 호출할 수 있다.

단, top-level function 을 사용하려면 import 를 해야 한다.

물론 IDE 가 보통 자동으로 해준다.

// Test.kt 
package com.example 
 
fun printTwo() { 
    print(2) 
} 

 
// Main.kt 
import com.example.printTwo 
 
fun main(args: Array<String>) { 
    printTwo() 
}

가시성 때문에 top-level function 을 정의할 때는 주의해야 한다.

자동완성에 손쉽게 노출되어 나중에 주체할 수 없는 지경에 이를 수 있기 때문이다.


top-level function 이 compile 될 때 다음과 같은 형태를 띈다.

public final class TestKt{
    public static void printTwo(){
        print(2)
    }
}

그래서 Java 에서 호출할 때 TestKt.printTwo() 와 같은 형태로 호출하는데..

Kt 가 붙은게 좋은 convention 은 아니기 때문에 @file:JvmName(“Printer”) 와 같은 annotation 을 넣어주면.

Java 에서 Printer.printTwo() 로 호출할 수 있다.



-

다른 파일에 정의한 top-level function 들이 하나의 class 로 compile 되길 원한다면 아래와 같이 하면 된다.

// Max.kt
@file:JvmName(“Math”)
@file:JvmMultifileClass
package com.example.math

fun max(n1: Int, n2:Int): Int = if(n1 > n2) n1 else n2

// Min.kt
@file:JvmName(“Math”)
@file:JvmMultifileClass
package com.example.math

fun min(n: Int, n2:Int): Int = if(n1 < n2) n1 else n2



-

Nothing type 은 empty type 이라고 부른다. 그 말은 instance 가 없다는 말이다.

Nothing 을 return 하는 함수는 return 을 하지 않는다는 말이다.

다시 말해 return statement 를 타지 않는다는 말이다.

이것은 무조건 exception 을 던지는 코드나 infinite loop 를 도는 코드들이 해당한다.



-

Nothing 은 모든 type 의 subtype 이기 떄문에 다음과 같은 코드가 가능하다.

fun fail(): Nothing = throw Error() 
val name:String = getName() ?: fail() // fail 은 Nothing 을 return



댓글0