2016년 12월 21일
코틀린 릴리스의 네 번째 마일스톤을 소개해드립니다. 우리는 1.1 버전의 개발을 마무리하고, 최종 릴리스를 2017년 Q1에 계획하고 있습니다. 대부분의 기능들이 이미 상당히 안정화되어 있으므로, 이제 시험해보고 피드백을 주시면 매우 감사하겠습니다. 많은 의견을 기대합니다!
다른 마일스톤 릴리스와 마찬가지로, 1.1의 새로운 언어 및 라이브러리 기능에 대한 역호환성 보장은 제공되지 않습니다. 1.1 마일스톤 릴리스에서 소개된 내용은 최종 1.1 릴리스 전에 변경될 수 있습니다.
이 릴리스와 관련하여 새로운 기능 또는 이 릴리스에서 겪는 어떠한 문제에 대한 피드백을 YouTrack, 포럼 및 Slack을 통해 공유해주시기 바랍니다.
이 마일스톤에서는 코루틴 구문 및 의미론의 중요한 재작업이 이루어져 코루틴을 더 단순하고 유연하게 만들었습니다. 또한 표준 라이브러리 개선, 새로운 언어 기능 및 컴파일러 플러그인, JS 백엔드의 다양한 기능 및 개선, 그리고 여러 가지 수정과 업데이트가 포함되어 있습니다.
또한 이 새 릴리스에는 Kotlin 1.0.6에서 소개된 모든 기능도 포함되어 있으며, Android Studio 2.3 Beta 1과의 호환성 업데이트도 포함되어 있습니다.
전체 변경 로그는 여기에서 확인하실 수 있으며, 몇 가지 주요 변경 사항은 아래에 나열되어 있습니다:
코루틴
코루틴 디자인을 크게 재검토하여 더 간단하고 조립 가능하며 강력한 형태로 만들었습니다:
모든 중단 및 코루틴 빌더 함수는 이제 직관적인 시그니처를 갖습니다(이제 더 이상 이상한 변환을 기억할 필요가 없습니다).
중단 함수와 해당 중단 함수 타입의 기본 언어 개념만 존재합니다. 특별한 코루틴 키워드는 제거되었습니다. 코루틴은 이제 단순히 표준 라이브러리의 startCoroutine 함수를 사용하여 시작되는 중단 가능한 계산의 인스턴스입니다.
복잡한 중단 함수는 보다 기본적인 중단 함수들로 구성될 수 있습니다. 이 릴리스에서는 다른 중단 함수를 호출할 수 있지만, 이 제한은 미래에 해제될 예정입니다.
중단 함수는 모든 콜백 스타일의 API를 래핑하고, 모든 비동기 코루틴 내에서 자유롭게 사용할 수 있습니다. 이제 컨트롤러가 더 이상 필요하지 않습니다. 동기적인 시퀀스를 빌드하는 generate 및 yield 쌍은 @RestrictsSuspension 주석을 사용하여 generate 블록 내의 중단을 제한합니다.
코루틴의 타입 추론이 이제 구현되었습니다. 대부분의 경우 코루틴 빌더에 대한 타입을 생략하고 자동으로 추론할 수 있습니다.
await 중단 함수는 이제 표준 라이브러리의 suspendCoroutine 중단 함수로의 꼬리 호출을 통해 구현할 수 있습니다:
suspend fun <T> await(f: CompletableFuture<T>): T =
suspendCoroutine<T> { c: Continuation<T> ->
f.whenComplete { result, exception ->
if (exception == null) // the future has been completed successfully
c.resume(result)
else // the future has been completed with an exception
c.resumeWithException(exception)
}
}
해당하는 빌더는 async라고 부르며 startCoroutine 함수를 통해 구현됩니다:
fun <T> async(block: suspend () -> T): CompletableFuture<T> {
val future = CompletableFuture<T>()
block.startCoroutine(completion = object : Continuation<T> {
override fun resume(value: T) {
future.complete(value)
}
override fun resumeWithException(exception: Throwable) {
future.completeExceptionally(exception)
}
})
return future
}
이를 함께 사용하여 미래에 더 자연스러운 코드를 작성할 수 있습니다.
async {
val original = asyncLoadImage("...original...") // creates a Future
val overlay = asyncLoadImage("...overlay...") // creates a Future
...
// 이미지 로딩 대기 후 이미지가 모두 로드되면 applyOverlay(...)
return applyOverlay(original.await(), overlay.await())
}
그러나 퓨처는 코루틴을 위한 다양한 사용 사례 중 하나일 뿐입니다. 코루틴의 구현과 사용 사례에 대한 전체 개요는 개정된 KEEP 문서에서 확인하실 수 있습니다.
우리는 이제 코틀린을 위한 코루틴 디자인을 크게 개선하였다고 생각하지만, 충분히 테스트되지 않았음을 알고 있습니다. 따라서 이를 선택적으로 실험적으로 제공할 계획이며, 이 마일스톤부터는 코루틴을 사용할 때 "이 기능은 실험적입니다: 코루틴" 경고가 표시됩니다. -Xcoroutines=enable 컴파일러 플래그로 이 경고를 해제하거나 -Xcoroutines=error 컴파일러 플래그로 이 기능을 비활성화할 수 있습니다. 해당 옵션은 IntelliJ IDEA의 코틀린 컴파일러 설정에서도 사용할 수 있습니다. Gradle 프로젝트에서 이 옵션을 설정하려면 local.properties 파일에 kotlin.coroutines=enable 또는 kotlin.coroutines=error를 추가하면 됩니다.
만약 kotlinx.coroutines 라이브러리를 사용 중이라면, 코루틴 디자인의 최신 변경 사항에 맞추어 업데이트된 0.2-alpha-1 버전을 사용하시기 바랍니다. 이 버전에서는 generate 스코프 내의 yieldAll 메서드도 소개되었습니다. 자세한 내용은 readme 파일을 참조하십시오.
언어 기능
속성의 타입은 getter로부터 추론될 수 있습니다
아래 코드에서 속성 foo의 타입은 String으로 추론됩니다. 자세한 내용은 이슈 KT-550을 참조하십시오.
val foo get() = ""
부동소수점 관련 기능, 수정 및 개선
이제 부동소수점 숫자 비교는 타입이 정적으로 Double 또는 Float인 경우 IEEE 754 호환 비교를 사용합니다. 부동소수점 숫자의 범위에 대해서는 특수화된 ClosedFloatingPointRange 인터페이스를 도입했습니다. 이 인터페이스는 고유의 비교 메서드를 제공하여 coerceIn과 같은 범위를 활용한 확장 작업을 구현할 수 있도록 합니다. 그 인스턴스는 두 개의 Float 또는 Double 값을 사용하여 호출되는 연산자 ..을 통해 얻을 수 있습니다. 세부 내용은 KT-4481과 KT-14651을 참조하십시오.
대리된 속성 바인딩의 가로채기
이제 provideDelegate 연산자를 사용하여 속성에 대한 대리자와의 바인딩을 가로챌 수 있습니다.
예를 들어, 바인딩하기 전에 속성 이름을 확인하려면 다음과 같이 작성할 수 있습니다:
class ResourceLoader<T>(id: ResourceID<T>) {
operator fun provideDelegate(thisRef: MyUI, property: KProperty<*>): ReadOnlyProperty<MyUI, T> {
checkProperty(thisRef, property.name)
... // property creation
}
private fun checkProperty(thisRef: MyUI, name: String) { ... }
}
fun <T> bindResource(id: ResourceID<T>): ResourceLoader<T> { ... }
class MyUI {
val image by bindResource(ResourceID.image_id)
val text by bindResource(ResourceID.text_id)
}
여기서 provideDelegate 메서드는 클래스 MyUI의 생성자 초기화자에서 호출됩니다. 따라서 속성 일관성을 생성할 때 확인할 수 있습니다. 이전에는 이와 같은 확인은 getter 또는 setter 호출시에만 가능했습니다.
아직 이 기능은 제대로 문서화되지 않았습니다. 하지만 초기 참조로 이 임시 문서를 사용할 수 있습니다.
JDK의 일부 메서드의 향상된 nullability
JDK의 일부 함수는 문서에서 nullability 계약을 정의하며, 일부는 null 값을 허용하지 않고, 일부는 결코 null을 반환하지 않으며, 또 다른 일부는 때에 따라 null을 반환할 수 있습니다.
불행하게도 JDK는 이러한 계약을 나타내기 위해 어노테이션을 사용하지 않고 문서에서만 설명합니다. 1.0 이전에는 JDK에 대한 외부 어노테이션 아티팩트를 사용하여 컴파일러에 제공하여 JDK 함수의 시그니처를 변경할 수 있었지만, 이 접근 방식은 충분히 신뢰할 수 없었습니다.
이제 우리는 또 다른 접근 방식을 소개하고 있습니다: JDK 시그니처를 향상하기 위해 필요한 정보를 직접 컴파일러에 포함시키는 것입니다. 첫 번째 단계로 작은 API 하위 집합의 nullability를 다루고 있습니다:
- java.util.Optional 팩토리 및 멤버 함수:
- of: null 값을 허용하지 않음
- ofNullable: null 값이 허용되며, non-nullable 유형의 Optional을 반환합니다.
- get은 항상 non-nullable 값을 반환합니다.
- java.lang.ref.Reference 및 WeakReference, SoftReference와 같은 모든 하위 클래스를 포함한 것:
- get은 nullable 값을 반환하며, 참조된 객체가 가비지 수집되면 언제든지 null이 될 수 있습니다.
- Kotlin 내장 컬렉션 인터페이스의 플랫폼 종속 함수로 노출되는 JDK의 Iterator, Iterable, Collection, List, Map의 기본 메서드.
- Java 함수형 타입은 이제 비플랫폼 타입으로 구성될 때 비플랫폼 타입의 호출 메서드에 비플랫폼 타입이 있습니다.
이러한 향상은 대부분의 경우 안전합니다. 특히 향상된 유형이 반환 위치에서 더 구체적인(비-nullable) 유형이거나 매개 변수 위치에서 더 일반적인(nullable) 경우 안전합니다. 그러나 유형이 반대 방향으로 변경되면 변경이 파괴적일 수 있습니다.
런타임에서 올바른 nullability를 준수하지 않으면 예외가 발생하는 경우를 제외하고는 이러한 파괴적인 개선을 도입하지 않으려고 합니다. 예를 들어, Optional.of는 이제 non-nullable 인수를 사용하므로 더 제한적이지만, 이 메서드에 null을 전달하려고 하면 어쨌든 예외가 발생하게 됩니다.
반면에 File.listFiles의 올바른 nullability를 지정하지 않기로 결정했습니다. 이 메서드는 때로는 null을 반환할 수 있지만, 대부분의 경우 예외를 던지는 것 외에는 의미 있는 대안이 없기 때문입니다.
기타 변경 사항
- 공개 인라인 함수에서 비공개 멤버를 사용하는 문제는 이제 @PublishedApi 어노테이션을 사용하여 해결할 수 있습니다. 내부 멤버에 적용하면 공개적으로 효과적으로 사용 가능한 공개 멤버가 됩니다. 자세한 내용은 KT-12215을 참조하십시오.
- const val은 이제 호출 위치에서 인라인화됩니다(KT-11734 참조).
- SAM 변환은 이제 오버로드 결정에서 일반 멤버와 동일한 우선순위를 갖습니다. 이는 KT-11128과 같은 문제를 해결합니다.
- % (나머지) 연산자의 모듈 이름 선택은 몇 가지 좋지 않은 결과를 초래할 수 있는 실수로 간주됩니다(KT-14650 참조). 따라서 우리는 rem 연산자를 도입하고 mod를 사용하지 않도록 제공합니다. 이 전환을 원활하게 진행하기 위한 모든 도구를 제공합니다.
표준 라이브러리
문자열에서 숫자로의 변환
유효하지 않은 숫자에 대해 예외를 던지지 않고 문자열을 숫자로 변환하는 String 클래스의 새로운 확장 기능이 있습니다: String.toIntOrNull(): Int?, String.toDoubleOrNull(): Double? 등.
이러한 함수는 결과 숫자를 반환하기 전에 박싱되므로 반환 유형이 해당되는 것으로 가정됩니다.
또한 Int.toString()와 같은 정수 변환 함수, String.toInt(), String.toIntOrNull()에는 변환 기수를 지정할 수 있는 오버로드가 추가되었습니다.
이 함수들의 개발에 상당한 기여를 한 Daniil Vodopian에게 감사드립니다.
onEach
onEach는 컬렉션 및 시퀀스에 대한 작은 확장 함수로서, 컬렉션/시퀀스의 각 요소에 대해 작업을 수행하고 부작용을 포함할 수 있게 해줍니다.
반복 가능한 객체에서는 forEach와 유사하게 동작하지만, 반복 가능한 객체 인스턴스를 반환합니다. 시퀀스에서는 요소가 반복되는 동안 주어진 작업을 지연 적용하는 래핑 시퀀스를 반환합니다.
초기 프로토 타입을 개발한 Christian Brüggemann에게 감사드립니다.
JavaScript 백엔드
@native 대신 external 사용
이 마일스톤부터 @native 어노테이션이 사용되지 않게 되며 대신 external 수정자를 사용해야 합니다.
JVM 대상과 달리 JS 대상에서는 클래스와 속성에 external 수정자를 사용할 수 있습니다.
참고로, 외부 클래스의 멤버를 external로 표시할 필요는 없습니다. 이 수정자는 멤버에 자동으로 상속됩니다. 따라서 다음과 같이 작성할 수 있습니다.
@native fun alert(message: Any?): Unit {}
대신에 다음과 같이 작성할 수 있습니다.
external fun alert(message: Any?)
개선된 가져오기 처리
JavaScript 모듈에서 가져와야 할 선언을 더 정확하게 설명할 수 있습니다.
외부 선언에 @JsModule("<module-name>") 어노테이션을 추가하면 컴파일 중에 해당 선언이 모듈 시스템 (CommonJS 또는 AMD)으로 올바르게 가져와집니다. 예를 들어, CommonJS를 사용하는 경우 해당 선언은 require(...) 함수를 통해 가져옵니다.
또한 모듈 또는 전역 JavaScript 객체로 선언을 가져올 경우 @JsNonModule 어노테이션을 사용할 수 있습니다.
아래의 전체 예를 살펴보겠습니다. 다음과 같이 Kotlin 소스 파일에 jQuery 라이브러리를 가져올 수 있습니다:
@JsModule("jquery")
@JsNonModule
@JsName("$")
external abstract class JQuery {
fun toggle(duration: Int = 0): JQuery
fun click(handler: (Event) -> Unit): JQuery
}
@JsModule("jquery")
@JsNonModule
@JsName("$")
external fun JQuery(selector: String): JQuery
이 경우에 JQuery는 jquery라는 모듈로 가져오거나 Kotlin 컴파일러가 구성된 모듈 시스템에 따라 $-객체로 사용할 수 있습니다.
이러한 선언을 다음과 같이 응용 프로그램에서 사용할 수 있습니다:
fun main(args: Array<String>) {
JQuery(".toggle-button").click {
JQuery(".toggle-panel").toggle(300)
}
}
이 스니펫에 대한 CommonJS 및 "평범한" 모듈 시스템에 대한 생성된 JS 코드를 확인할 수 있습니다.
이를 시도하는 방법
Maven/Gradle에서: 빌드 스크립트와 프로젝트를 위한 저장소로 http://dl.bintray.com/kotlin/kotlin-eap-1.1을 추가하고, 컴파일러 및 표준 라이브러리의 버전 번호로 1.1-M04를 사용하십시오.
IntelliJ IDEA에서: 도구 → Kotlin → Kotlin 플러그인 업데이트 구성으로 이동한 다음, 업데이트 채널 드롭다운 목록에서 "Early Access Preview 1.1"을 선택하고 업데이트를 확인하십시오.
커맨드 라인 컴파일러는 Github 릴리스 페이지에서 다운로드할 수 있습니다.
try.kotlinlang.org에서 사용하세요. 오른쪽 하단 모서리의 드롭다운 목록을 사용하여 컴파일러 버전을 1.1-M04로 변경할 수 있습니다.
즐거운 Kotlin 사용하세요!
원문
https://blog.jetbrains.com/kotlin/2016/12/kotlin-1-1-m04-is-here/
'Kotlin > Release Notes' 카테고리의 다른 글
[Kotlin Release Notes] Kotlin 1.1 Beta Is Here! (0) | 2023.09.03 |
---|---|
[Kotlin Release Notes] Kotlin 1.0.6 is here! (0) | 2023.09.03 |
[Kotlin Release Notes] Kotlin 1.1-M03 is here! (0) | 2023.09.03 |
[Kotlin Release Notes] Kotlin 1.0.5 is here (0) | 2023.09.02 |
[Kotlin Release Notes] Kotlin 1.1-M02 is here! (0) | 2023.09.02 |
댓글