Hanbit the Developer

Kotlin Documentation | Inline functions 본문

Mobile/Kotlin

Kotlin Documentation | Inline functions

hanbikan 2023. 5. 23. 17:33

Kotlin Documentation 시리즈에 대해

Category: Concepts - Functions

문서 링크: https://kotlinlang.org/docs/inline-functions.html


higher-order function는 객체이며 메모리를 추가로 할당하고 virtual call을 발생시키기 때문에 오버헤드가 발생한다.

아래 코드를

lock(l) { foo() }

아래로 치환하게 되면 이러한 오버헤드가 줄어들게 된다. 함수 객체를 파라미터로 받는 대신 컴파일러가 아래의 코드를 생성한 것이다.

l.lock()
try {
    foo()
} finally {
    l.unlock()
}

이는 아래와 같이 inline 키워드를 추가함으로써 적용할 수 있다.

inline fun <T> lock(lock: Lock, body: () -> T): T { ... }

noinline

inline 함수에서 특정 함수를 inline 취급하고 싶지 않다면 해당 함수 앞에 noinline을 붙이면 된다.

inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) { ... }

Non-local returns

inline function에서 바깥 함수에서의 반환을 유도할 수 있다. 람다에 위치해있지만 람다를 감싸고 있는 함수에서 탈출하는 것을 non-local returns라고 부른다.

fun foo() {
    ordinaryFunction {
        return // ERROR: cannot make `foo` return here
    }
}
fun foo() {
    inlined {
        return // OK: the lambda is inlined
    }
}

crossinline

전달된 inline function이 내부에서 직접 실행되는 것이 아니라 다른 컨택스트에서 실행되는 경우, non-local control flow가 허용되지 않는다. 해당 inline function이 non-local returns가 불가능하다는 것을 명시하기 위해, crossinline을 사용한다.

inline fun f(crossinline body: () -> Unit) {
    val f = object: Runnable {
        override fun run() = body()
    }
    // ...
}

*다른 컨택스트에서 사용함에도 불구하고 crossinline을 명시하지 않으면 컴파일 에러가 발생한다.

Reified type parameters

인자로 전달된 타입에 접근하기 위해, reified를 사용한다.(대안: reflection)

inline fun <reified T> TreeNode.findParentOfType(): T? {
    var p = parent
    while (p != null && p !is T) {
        p = p.parent
    }
    return p as T?
}

Inline properties

val foo: Foo
    inline get() = Foo()

var bar: Bar
    get() = ...
    inline set(v) { ... }

프로퍼티 전체에 inline을 마킹하는 경우 get(), set() 모두에 inline을 적용하게 된다.

inline var bar: Bar
    get() = ...
    set(v) { ... }