본문
171215(금) - Kotlin docs (Inline Functions)
Kotlin docs
Inline Functions
- higher-order functions를 사용하면 runtime penalties가 부여된다.
- each function은 object이며 function의 body에서 accessed되는 variables인 closer를 캡쳐한다. (?)
- memory allocations (both function objects and classes) and virtual calls는 runtime overhead를 초래한다.
- 이러한 많은 종류의 overhead case들은 inlining the lambda expressions를 사용함으로써 eliminated 된다.
- lock() function은 call-sites에서 쉽게 inline 될 수 있다.
lock(l) { foo() }
- parameter에 대한 function object를 만들고 generating call을 하는 대신 compiler에서 아래 코드를 생성 가능하다.
l.lock() try { foo() } finally { l.unlock() }
- compiler가 위와같이 만들게 하려면 inline modifier를 mark해야한다.
inline fun <T> lock(lock: Lock, body: () -> T): T { // ... }
- inline modifier는 function itself와 전달된 lambdas에 영향을 미치고 모두 call site로 inlined된다.
- inline하면 code가 더 커질 수 있다. 하지만 reasonable way로 loop를 수행하면 performance가 좋을 것이다.
- 특히 loop내부의 megamorphic call-sites에서 효과가 좋다.
noinline
- inline functions에 전달된 일부 lambdas만 inline되도록 하려면 noinline modifier를 사용해서 function parameters중 일부를 표시할 수 있다.
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) { // ... }
- inlinable lambdas는 inline functions 내에서만 call 되거나 inlinable arguments로 전달 될 수 있다.
- 하지만 noinline은 stored in fields, passed arounds 등 어떤 방식으로든 사용가능
- inline function에 inlinable functions and reified type parameters가 없으면, compiler에서 해당 functions를 inline하게되면 매우 유용하지 않으므로 compiler는 warning을 표시한다. (@Suppress("NOTHING_TO_INLINE")사용으로 warning 해제 가능)
Non-local returns
- kotlin에서는 non named function or anonymous function을 exit하기 위해 unqualified return만 사용할 수 있다.
- lambda를 exit하려면 label을 사용해야 하고 lambda안에서 bare return을 금지한다.
fun foo() { ordinaryFunction { return // ERROR: can not make `foo` return here } }
- 그러나 lambda 전달된 function가 inline이라면 return도 inline 될 수 있으므로 사용 가능하다.
fun foo() { inlineFunction { return // OK: the lambda is inlined } }
- 이러한 return을 non-local returns라고 부른다.
fun hasZeros(ints: List<Int>): Boolean { ints.forEach { if (it == 0) return true // returns from hasZeros } return false }
- 일부 inline functions는 parameter로 전달된 lambdas를 function body에서 직접 call 하지 않고 local object나 nested function 같은 다른 context에서 호출 가능하다.
- 이런 경우 lambdas에서도 non-local control flow는 허용되지 않는다.
- 이를 나타내기 위해 lambda parameter에 crossinline modifier가 필요
inline fun f(crossinline body: () -> Unit) {
val f = object: Runnable {
override fun run() = body()
}
// ...
}
- break와 continue는 아직 inline lambdas에서 사용 불가능하지만 support할 계획이 있다.
Reified type parameters
'Mobile > Kotlin' 카테고리의 다른 글
181023(화) - Kotlin Coroutine (Channel) (1) | 2018.10.23 |
---|---|
180102(화) - in & out, covariant & contravariance (0) | 2018.01.03 |
171212(화) - Kotlin docs (Object Expressions and Declarations) (0) | 2017.12.12 |
171212(화) - any (0) | 2017.12.12 |
171211(월) - Using scope functions (0) | 2017.12.11 |
댓글