trademarks and Coupang logos and service marks used are registered in the United States and other countries, Coupang, inc. And/or the property of its affiliates (collectively referred to as “Coupang”). Other companies mentioned herein are mentioned for identification purposes only, and Coupang acknowledges that the name of the company used may be a registered trademark of the company and that company alone has exclusive ownership of the trademark. The information contained herein is based on the author's personal experience as an executive and employee and does not represent Coupang's views or opinions. Coupang has not verified the adequacy, fairness, accuracy, or stability of the information contained herein, nor does it make any representations about it
인라인 밸류 클래스 • 트레일링 콤마 • 함수형 인터페이스 • 위임 프로퍼티 • 바운드 호출가능한 레퍼런스 • 람다에서 비구조화 • 어노테이션의 배열 리터럴 • 지역 지연 초기화 변수 • 옵트인 어노테이션 • 확실히 널이 아닌 타입 • 서브젝트가 있는 when • 어노테이션 클래스의 인스턴스화 • … • 타입 별칭 • 실드 클래스와 인터페이스 • 계약 • when 안에 break/continue • 철저한 when • 빌더 추론 • ..< 연산자 • 데이터 객체 • 효율적인Enum.entries
(FIR) ◦ 언어 구성은 더 단순한 구성으로 나뉩니다. • 분석에 있어 단계별 접근 ◦ Import, 어노테이션, 타입등의 언어 구성에 대한 개별적인 단계 ◦ IDE와 컴파일러 플러그인을 위한 확장 • 새로운 제어 흐름 엔진, 향상된 타입 추론과 레졸루션 ◦ 코드를 통해 데이터 흐름 정보를 전달
스마트 캐스트의 추가! - KT-7186 Smart cast for captured variables inside changing closures of inline functions - KT-4113 Smart casts for properties to not-null functional types at invoke calls - KT-25747 DFA variables: propagate smart cast results from local variables - KT-1982 Smart cast to a common supertype of subject types after || (OR operator) - …
purr") } } fun petAnimal(animal: Any) { val val isCat = animal is Cat if (isCat) { animal.purr() // OK in 2.0 } } 2.0: 합성 데이터 흐름 변수가 스마트 캐스트에 관한 정보를 전파한다.
cardWithHolder = card is Card && !card.holder.isNullOrEmpty() return when { cardWithHolder -> { card.holder } else -> "none" } } Any -> Card String? -> String String으로 스마트캐스트 제약을 포함하여 모든 스마트 캐스트에 대한 일반 규칙이 작동한다. 변수로부터 스마트 캐스트
callInPlace 계약이 있는 것 처럼 취급합니다. fun indexOfMax(a: IntArray): Int? { var maxI: Int? = null a.forEachIndexed { i, value > // 2.0: OK if (maxI == null | a[maxI!!] <= value) { maxI = i } } return maxI }
with early return • KT-13650 Right-hand side of a safe assignment is not always evaluated, which can fool smart-casts • KT-18130 Smart cast can be broken by expression in string template • KT-22454 Unsound smartcast in nested loops with labeled break from while-true • KT-17694 Smart cast impossible on var declared in init block with a secondary constructor • KT-56867 Green in K1 -> red in K2 for unsound code. `catch_end` to `good_finally` data flow • KT-26148 No smartcasts when not-null assertion or not-null assignment in lambda (contract functions with EXACTLY_ONCE or AT_LEAST_ONCE effects) • KT-23249 Inconsistent union type between platform type and non-platform type in K1. Fixed in K2 • KT-27261 Contracts for infix functions don't work (for receivers and parameters) • KT-30507 Unsound smartcast if null assignment inside index place and plusAssign/minusAssign is used • KT-52424 ClassCastException: Wrong smartcast to Nothing? with if-else in nullable lambda parameter • KT-37838 Support smart cast for inner/nested contracts • KT-30756 No smartcast if elvis operator as a smartcast source in while or do-while is used as the last statement • KT-53802 No smartcast after a while (true) infinite loop with break • …
향상 - 도구: 앰퍼 그래들 프로젝트 격리, 노트북, 빌드 리포트 - 라이브러리: kotlinx-datetime, kotlinx-io, kotlinx-kover and others - 컴파일러: Kotlin/Wasm, 향상된 자바 상호호환, 타겟 전체의 인라인 문맥 통합 - 언어 자체…
value: T) class IntContainer : Container<Int>(42) class StringContainer : Container<String>("Kotlin") fun <A> unbox(container: Container<A>): A = container.value // OK! fun <A> unboxAndProcess(container: Container<A>): A = when (container) { is IntContainer -> container.value // 컴파일 안됨 is StringContainer -> container.value // 컴파일 안됨 }
sealed class Container<T>(val value: T) class IntContainer : Container<Int>(42) class StringContainer : Container<String>("Kotlin") fun <A> unbox(container: Container<A>): A = container.value // OK! fun <A> unboxAndProcess(container: Container<A>): A = when (container) { is IntContainer -> container.value // 컴파일 안됨 is StringContainer -> container.value // 컴파일 안됨 }
sealed class Container<T>(val value: T) class IntContainer : Container<Int>(42) class StringContainer : Container<String>("Kotlin") fun <A> unbox(container: Container<A>): A = container.value // OK! fun <A> unboxAndProcess(container: Container<A>): A = when (container) { is IntContainer -> 42 is StringContainer -> “Kotlin” }
T) class IntContainer : Container<Int>(42) class StringContainer : Container<String>("Kotlin") fun <A> unbox(container: Container<A>): A = container.value // OK! fun <A> unboxAndProcess(container: Container<A>): A = when (container) { is IntContainer -> container.value // A = Int; GADT 스타일 스마트 캐스트 is StringContainer -> container.value // A = String; GADT 스타일 스마트 캐스트 }
String) fun process(user: User) { val (surname, firstName) = user // … } Error in 2.x: - “surname” doesn’t match the property “name” - “firstName” doesn’t match the property “lastName”
component 함수를 사용하지 않음 - 새로운 이름으로 대입할 때를 위한 특별한 문법 도입 data class User(val name: String, val lastName: String) fun process(user: User) { val (name, lastName) = usern // OK // … }
= PaddingValues(0.dp), val reverseLayout: Boolean = false, val verticalArrangement: Arrangement.Vertical = If (!reverseLayout) Arrangement.Top else Arrangement.Bottom, val horizontalAlignment: Alignment.Horizontal = Alignment.Start, val userScrollEnabled: Boolean = true ) KT-8214 2.2의 예비 변경 사항
[predicate]. */ fun <T> Sequence<T>.last(predicate: (T) -> Boolean): T { var result: T? = null for (element in this) if (predicate(element)) result = element return result ?: throw NoSuchElementException("Not found") }
(T) -> Boolean): T { var last: T? = null var found = false for (element in this) { if (predicate(element)) { last = element found = true } } if (!found) throw NoSuchElementException("Not found") @Suppress("UNCHECKED_CAST") return last as T }
T { var result: Any? = null for (element in this) if (predicate(element)) result = element if (result == NotFound) throw NoSuchElementException("Not found") return result as T }
Sequence<T>.last(predicate: (T) -> Boolean): T { var result: Any? = null for (element in this) if (predicate(element)) result = element if (result == NotFound) throw NoSuchElementException("Not found") return result as T }
연구중 private error object NotFound fun <T> Sequence<T>.last(predicate: (T) -> Boolean): T { var result: T | NotFound = NotFound for (element in this) if (predicate(element)) result = element if (result is NotFound) throw NoSuchElementException("Not found") return result }
위치에도 확장 가능 - 특별 연산자도 에러를 지원: ?. !. 연구중 에러를 위한 유니온 타입 private error object NotFound fun <T> Sequence<T>.last(predicate: (T) -> Boolean): T { var result: T | NotFound = NotFound for (element in this) if (predicate(element)) result = element if (result is NotFound) throw NoSuchElementException("Not found") return result }
city: LiveData<String> field mutableCity = MutableLiveData<String>() } val background: Color field = mutableStateOf(getBackgroundColor) get() = field.value KEEP-278, KT-14663 2.2에 업데이트