Kotlin 1.3
What's new?
Kittinun Vantasin
About me
Mobile Enthusiastic 📱🍭
💖 Kotlin + Open source
Works at Merpay in Tokyo 🗼
github.com/kittinunf
@kittinunf
About me
from wonderful land of smiles ☺️
loves thai food because it is yummy 😋
rides Tuktuk while in Bangkok 💨
Kotlin 1.3
2010 Started
2011 Revealed
Late 2012 OSS
2014
Gain popularity
2016
Hit 1.0
2017
Hit 1.1
Late 2017
Hit 1.2
2018
Hit 1.3
What's new?
Contracts
Capture variable in local when scope
@JvmStatic & @JvmField in interfaces
fun main()
255 arity function
inline classes! + USignedTypes
consistent empty related functions
etc.
Guide
Kotlin 1.2.71 or earlier
Awesome Kotlin 1.3
Contracts
fun foo(s: String?) {
s?.let {
s.length // smart cast is here
}
if (s.isNotNull()) {
s?.length // no smart cast here :(
}
}
fun String?.isNotNull() = this != null
fun foo(s: String?) {
s?.let {
s.length // smart cast here
}
if (isNotNull(s)) {
s.length // also smart cast here
}
}
fun isNotNull(value: Any?): Boolean {
contract { returns(true) implies (value != null) }
return value != null
}
Contracts cont.
val myValue: String
myRun {
myValue = "Hello, World!" // Error here ... :(
}
fun <R> myRun(block: () -> R): R {
return block()
}
val myValue: String
myRun {
myValue = "Hello, World!" // Woohoo it works!
}
fun <R> myRun(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
Capture when scope
val answer = calculate()
return when(answer) {
42 -> "Right answer!"
123 -> "ARGHHHHH!"
else -> "Sorry, $answer is not correct"
}
answer // I don't want to see you here
return when(val answer = calculate()) {
42 -> "Right answer!"
123 -> "ARGHHHHH!"
else -> "Sorry, $answer is not correct"
}
//answer you are not being seen here
@JvmStatic & @JvmField
interface Foo {
companion object {
@JvmField
val bar: Int = 42
@JvmStatic
fun sayHello(name: String = "") {
println("Hello, $name")
}
}
}
fun main()
fun main() {
println("Hello, world")
}
// compare to the full-blown version
fun main(args : Array<String>) {
println("Hello, world")
}
255 Arity function
fun onlyRealManCanUnderstandThis(
block: (Any, Any, Any, /* 250 more */, Any, Any
) {
block(Any(), Any(), /* 250 more */, Any(), Any())
}
@SinceKotlin("1.3")
interface FunctionN<out R> : Function<R> {
operator fun invoke(vararg args: Any?): R
override val arity: Int
}
Inline classes!!
class FirstNameInKana(n: String)
class LastNameInKana(n: String)
fun formattedName(f: FirstName, l: LastName) {
println("$l $f")
}
formattedName(
FirstNameInKana("やまだ"),
LastNameInKana("たろう")
)
typealias FirstName = String // OK, but meh :|
typealias LastName = String // OK, but meh :|
inline class FirstNameInKana(n: String)
inline class LastNameInKana(n: String)
fun formattedName(f: FirstName, l: LastName) {
println("$l $f")
}
formattedName(
FirstNameInKana("やまだ"),
LastNameInKana("たろう")
)
Inline classes cont.
Must have a public constructor with a single val
No init block
Must be final
Cannot extend anything - implement interfaces OK
Cannot have any additional properties
Must be a top level class
HANDLE WITH CARE
UTypes FTW
// Literal shortcode for UInt
val aUInt: UInt = 3u
val aULong: ULong = 3uL
// And from Hex...
val hexUByte: UByte = 0xFFu // 255
val hexUShort: UShort = 0xFFFFu // 65535
val hexUInt: UInt = 0xFFFF_FFFFu // 4294967295
val hexULong: ULong = 0xFFFF_FFFF_FFFF_FFFFu // xD
Empty related func.
fun calculateArray(): Array<Int>? {
// some calculation
}
val array = calculateArray()
array.isNullOrEmpty() // ERRRAARGGHHH, there is none
fun calculateArray(): Array<Int>? {
// heavy calculation
}
val array = calculateArray()
if (array.isNullOrEmpty()) {
// :) Joy
}
val maybeArray: Array<T>
maybeArray.isNullOrEmpty()
val maybeCollection: Collection<T>
maybeCollection.isNullOrEmpty()
val maybeMap: Map<T, U>
maybeMap.isNullOrEmpty()
Empty related func.
val listOfFeatures: List<String> = ...
println(listOfFeatures.ifEmpty {
listOf("Default1", "Default2")
})
val townProvidedByUser: String = ...
println(townProvidedByUser.ifBlank { "東京" })
Serialization Library
@Serializable
data class Destination(
val name: String? = "",
val country : String? = "",
val code : Int = 0,
@Optional
val isMetro : Boolean = false,
@Transient
val favorite : Boolean = false
)
val tokyoAsString = JSON.stringify(
Destination(name = "東京", country = "Japan")
) // { "name":"東京","country":"Japan","code":0 }
val tokyo = JSON.unquoted.parse<Destination>(
"{ name:東京,country:Japan, code:12 }"
) // Destination(name = "東京", country = "Japan", code = 12)
Caveats
The experimental feature is really experimenting!
They can be breaking for the next version! :)
How do you feel about 1.3?
Q & A
Kotlin 1.3, What's new?
By Kittinun Vantasin
Kotlin 1.3, What's new?
- 1,205