قالب وردپرس درنا توس
Home / IOS Development / What's New in Kotlin 1.3

What's New in Kotlin 1.3



Kotlin has come a long way since its first release in July 2011. It was originally designed as a replacement for Java to be used by JetBrain's programmers, who were frustrated by Java's limitations and found that their preferred language, Scala, compiled too slowly. Since then, it has grown from an interesting side project, used by a handful of developers, to the preferred language Google for Android development.

Kotlin integrates into other platforms, with the Kotlin-to-JavaScript Web Development Transpiler and Kotlin / Native, which aims to unify Kotlin into native applications running on iOS, MacOS, Windows, Linux and WebAssemble.

It also makes sense in the hearts and minds of developers. HackerRank's 201

9 Developer Skills Report, based on their survey of over 70,000 participants, lists Kotlin as one of the top 3 programming languages ​​developers want to learn in 2019.

Kotlin 1.3 has been around since October 2018, but it doesn't mean that it is too late to look into the features provided by this latest version. Kotlin is still new to many developers, including those who are developing Android apps for their lives.

In this tutorial you will learn about the most important changes in Kotlin 1.3.

Kotlin Playground

One of the most useful recent programming trends is the playground. An interactive environment that lets you go in and then run snippets and see the results without having to set up a whole new project. They are useful for learning a new language or framework and for answering "What if I tried this?". Questions.

It is a simplified online IDE that lets you enter Kotlin code, execute it, and even share it by providing a link to your code, or as a built-in iframe that you can include on a website.

Let's try out the Kotlin Playground. Point your favorite reader at play.kotlinlang.org. You will be taken to a web page that looks like this:

Click the Run button to run the sample code provided by Kotlin Playground. An exit route with the text Hello, the world !!! appears at the bottom of the page.

Before proceeding, click the Settings button. This popup will appear:

This allows you to select which version of Kotlin to use when you click the Run button. Select the latest 1.3 version in the Kotlin Version menu. At the time of writing, it is 1.3.40 .

Now that you've got the playground set up, it's time to try out some Kotlin 1.3 features!

Language Improvances

Main Function without Arguments

Each program has a entry point when running the program. Thanks to the influence of C, the entry point for programs in many programming languages ​​is called main () . It is in every Kotlin application, also in an Android Studio project.

Another C-convention borrowed from Kotlin is that main () takes a number of strings as its argument. This matrix contains the parameters that follow the program name when running from the command line.

Until Kotlin 1.3, this was the only version of the main function () in Kotlin, and you have to type Hello, the world! programs like this: [19659019] fun main (args: Array ) {
println ("Greetings, user!")
}

The single argument, args contains the arguments sent to the Kotlin program when called from the command line.

In Kotlin 1.3, you would simply ignore the args . You can use a new form of main () that does not take any arguments at all. This is useful for applications where you do not expect command line parameters, including those you want to type on Kotlin Playground.

Run the following in Kotlin Playground:

  fun main () {
println ("Greetings, user!")
}

It works as you expect, without arguments.

Subject Capture

The Kotlin 1.3 enhancement that you are most likely to use is when the keyword new topic captures ability.

Consider the following:

  fun fastCheapOrGood (): String {
return when (determOutcome ()) {
0 -> "Quick."
1 -> "Cheap."
2 -> "Good."
else -> "None of the standard outcomes."
}
}

The topic is the value that comes after then the keyword. In the function above, the topic is determOutcome () and the value determines which of when its cases are used.

Suppose you wanted to display the determOutcome () value in the case otherwise . In Kotlin 1.3, there was no way to "catch" then its subject. The usual solution is to declare an additional variable like this:

  val result = determOutcome ()
return when (outcome) {
0 -> "Quick."
1 -> "Cheap."
2 -> "Good."
else -> "None of the default outcomes: the selection was $ outcomes."
}

This works, but it introduces two complications:

  1. It introduces a new variable whose scope exists outside the then block. This is fine if you want to use outcomes outside of when but introduces the risk of side effects if you do not need the value of the outcome elsewhere.
  2. It adds an extra code line. It may not seem like such a bad thing, but consider Corbato & # 39; s Law: "Every programmer has a number of code lines they can write in a day, and that number is the same, regardless of programming language." that you should program in languages ​​and ways that allow you to do as much as possible, with as little code as possible.

This is where Kotlin 1.3's new prison record for when comes in. It allows you to declare a variable that captures when its subject, and whose scope is limited to when blocks:

  returns when (currency case = determOutcome ()) {
0 -> "Quick."
1 -> "Cheap."
2 -> "Good."
else -> "None of the default outcomes: the selection was $ outcomes."
}

Now there is a smaller line of code and a smaller lost variable.

Random Number

If you needed a random number generator for a desktop or mobile Kotlin project, you can always rely on Java Virtual Machine's Random class. But with Kotlin expanding beyond Android and other Java-based systems, it had to be a Kotlin-specific way of generating random numbers that work across platforms.

The solution is an abstract class that can implement any number of randomizing algorithms. If you do not need a cryptographically secure random number generator, the standard execution provided by Random.Default companion object should suit most needs.

Let's take Kotlins Random for a spin around. Run the following at Kotlin playground a few times:

  import kotlin.random. *

funny main () {
println ("$ {fastCheapOrGood ()}")
}

fun fastCheapOrGood (): String {
return when (determOutcome ()) {
0 -> "Quick."
1 -> "Cheap."
2 -> "Good."
else -> "None of the standard outcomes."
}
}

fun determOutcome (): Int {
return Random.nextInt (6) // Generates a random number between 0 and 5 included.
}

Random comes with many extension functions that save you having to use an extra line to declare an index variable to select a random item from an array or collection. Run this at Kotlin Playground:

  import kotlin.random. *

funny main () {
val colors = arrayOf ("amaranth", "coquelicot", "emerald")
println ("Random array element: $ {colours.random ()}")

val flavors = listOf ("maple", "bacon", "lemon curry")
println ("Random list item: $ {flavors.random ()}")
}

There are also extension functions that you can use to select a random character from a string or a random element from a range. Add the following to the end of main () and run the code again:

  val pangram = "How razorback-jumping frogs can level six piked gymnasts!"
println ("$ {pangram.random ()}")

val firstHalfOfAlphabet = & # 39; a & # 39; .. & # 39; l & # 39;
println ("Random range: $ {firstHalfOfAlphabet.random ()}")

Functions About Nothing

isNullOrEmpty () and orEmpty () can now be used on more than just nullable strings. You can now use them to get similar results with matrices and collections.

Run the following on Kotlin Playground:

  fun main () {
val nullArray: Array ? = null
val emptyArray = arrayOf  ()
val fillArray = arrayOf ("Alpha", "Bravo", "Charlie")

println ("nullArray.isNullOrEmpty (): $ {nullArray.isNullOrEmpty ()}") // true
println ("tomArray.isNullOrEmpty (): $ {tomArray.isNullOrEmpty ()}") // true
println ("fillArray.isNullOrEmpty (): $ {fillArray.isNullOrEmpty ()}") // false
println ("nullArray.orEmpty (): $ {(nullArray.orEmpty ()). joinToString ()}") // []
println ("fillArray.orEmpty (): $ {fillArray.orEmpty (). joinToString ()}") // ["Alpha", "Bravo", "Charlie"]
}

Kotlin 1.3 also introduces two new features about nothing. The first one, ifEmpty () allows you to execute a lambda if the matrix, collection, or string you are using it contains no elements.

Add the following to the end of main () and run the code again:

  val emptyString = ""
val nonEmptyString = "Not empty!"
println (emptyString.ifEmpt {"emptyString is empty"}) // emptyString is empty
println (nonEmptyString.ifEmpty {"emptyString is empty"}) // Not empty!

The other one, ifBlank () executes a lambda if the string you are using it on is nothing more than a space or is the empty string.

Add the following to the end of main () and run the code again:

  val space = ""
val newlinesTabAndReturns = " n  r  t  n  r  t"
val nonBlankString = "Not blank!"
println (space.ifBlank {"& # 39; space & # 39; empty"}) // & # 39; space & # 39; is empty
println (newlinesTabAndReturns.ifBlank {"& # 39; newlinesTabAndReturns & # 39; is empty"}) // & # 39; newlinesTabAndReturns & # 39; is empty
println (emptyString.ifBlank {"& # 39; TomString & # 39; is empty"}) // (empty string)
println (nonBlankString.ifBlank {"& # 39; nonBlankString & # 39; is empty"}) // Not blank!

Boolean

The Boolean type now has a companion object, which means there is something to associate extension functions with. To see a practical application of this new opportunity, run the following on Kotlin Playground:

  import kotlin.random. *

funny Boolean.coinToss (): Boolean = Random.nextBoolean ()
funny Boolean.asHeadsOrTails (): String {
if this) {
return "Heads"
} else {
return "Tails"
}
}
var penny = false
println ("Coin Box: $ {penny.coinToss (). asHeadsOrTails ()}")

HashCode

A HashCode takes an object of any size as input and outputs a string or number that is usually smaller than the object. The result of a hash function acts as a kind of fingerprint for its input object because if two objects are equal and fed into the same hash function, the results are also the same.

hashCode () takes an object of any size as input and outputs an integer. The object you specify as input to hashCode () may be one byte or one million bytes in size, but the output is always an integer (which takes 32 bytes).

Let's try hashCode () on a few strings. Run the following on Kotlin Playground:

  fun main () {
val shortString = "Hi."
val anotherShortString = "Here."
val mediumString = "It's hard to predict, especially about the future."
val longString = "Lorem ipsum dolor sit amet, consectetur adipiscing elite. Morbi neque nunc, elementum vitae consectetur ut, eleifend vitae ante. Donec sits amet feugiat risus. Morbi tristique tortor arcu, sed fringilla orci hendrerit own. Curabitur libero risus, hendrerit tincidunt enim quis, consectetur rhoncus metus. Etiam sed lacus mollis, pulvinar mauris nec, tincidunt purus. "

println ("shortStrings hashcode: $ {shortString.hashCode ()}") // 72493
println ("anotherShortStrings hash code: $ {anotherShortString.hashCode ()}") // 72493
println ("mediumStrings hashcode: $ {mediumString.hashCode ()}") // 642158843
println ("longStrings hashcode: $ {longString.hashCode ()}") // -420880130
}

Note that shortString and anotherShortString have the same hashCode () value. That's because they contain the same text, and therefore are the same.

In Kotlin 1.3, hashCode () has been extended to work for nullable types. The following simple rules are followed:

  1. If the object used is not zero, the hashCode () returns the hash function value of the object.
  2. If the object used is null, hashCode () returns 0.

Add the following to the end of main () and execute the code again:

  val yetAnotherShortString = "Hi."
select nullString: String? = null
println ("yetAnotherShortStrings hashcode: $ {yetAnotherShortString.hashCode ()}") // 72493
println ("nullStrings hashcode: $ {nullString.hashCode ()}") // 0

Coroutines

We saved the biggest change lately! Coroutines have been in Kotlin since version 1.1 as an experimental feature, and Kotlin 1.3 is the first version where they are a standard part of the language.

One way to describe coroutines is "a way to write asynchronous code using lightweight threads and a structured syntax". A less technical, more practical way of expressing this is "an easier to read way of programming things that happen at the same time".

Let's start with a simple example. Run the following on Kotlin Playground:

  import kotlinx.coroutines. *

funny main () {
// 1
GlobalScope.launch {
// 2
delay (1000L)
println ("And about a second later, this will be printed.")
}
// 3
println ("This will be printed first.")
// 4
Thread.sleep (2000L)
}

You should see the following in the print section of the page:

  This is printed first.
And about a second later, this is printed.

This is what happens in the code:

  1. The keyword is a coroutine builder, which starts a coroutine. It will run parallel to the current thread without blocking it. Each coroutine runs within a scope and runs within GlobalScope . When a coroutine is launched within this scope, the same scope as the application works, and the life of the coroutine is limited only by the application's lifetime.
  2. This is the code for coroutine. delay () stops the execution of the coroutine it is in for a specified number of milliseconds and then restores the execution when that time has elapsed, all without blocking the current thread. The coroutine waits for one second and then prints a message.
  3. This is the first line of code after the coroutine. The coroutine runs parallel to this code, and since it waits one second before printing the message, this println () is run first.
  4. This line keeps the program "alive" for another two seconds, giving the coroutine enough time to execute: one second for the delay, and the milliseconds it takes for the coroutine println () to do its thing. If you comment or remove this, the program's other production line will disappear.

Let's try another example. Run the following on Kotlin Playground:

  import kotlinx.coroutines. *

fun main () = runBlocking {// 1
launch {
delay (200L)
println ("After 200 millisecond delay.")
}
// 2
coroutineScope {
// 3
launch {
delay (500L)
println ("After 500 millisecond delay.")
}
delay (100L)
println ("After 100 millisecond delay.")
println ("$ {perform200msTask ()}")
}
// 3
println ("... and we're done!")
}
// 4
suspend fun perform200msTask (): String {
delay (200L)
return "Finished with a 200 ms task."
}

You see the following in the print section of the page:

  After 100 milliseconds delay.
After 200 millisecond delay.
Finished doing a 200 ms task.
After 500-millisecond delay.
... and we're done!

Here's what happens in the code:

  1. runBlocking keyword lets main () common block code, call suspension functions, which you can think of as a running feature like a coroutine.
  2. coroutineScope The keyword defines a scope for coroutines to "live" in. It can contain many coroutines, which allow you to group tasks that happen simultaneously. This code blocks the current thread until all the coroutines in it are completed.
  3. Because the previous block is a coroutineScope that is blocked, this line is not executed until the previous block is completed. This means that "… and we're done!" Last printed.
  4. stops cue tags as a suspending function . When called, it is executed in parallel.

To confirm that coroutineScope blocks the current thread until its internal coroutines are completed, make the following change to the code from this:

  // 2
coroutineScope {

For this:

  // 2
launch {

Run the code again. The exit will now look like this:

  ... and we're done!
After 100 millisecond delay.
After 200 millisecond delay.
Finished doing a 200 ms task.
After 500-millisecond delay.

With that change, everything before the final line of main () is executed in parallel and unblocked, and the control immediately jumps to that line. The result is that "… and we're done!" Will be printed first instead of last.

Using Kotlin 1.3 in Android Studio

Now you are eager to try Kotlin 1.3 in your Android projects. You can see which version of Kotlin your project is using by selecting Tools Kotlin from the menu, which will open this dialog:

If a newer version of Kotlin is available, you get the chance to install it:

Where to go from here?

The first place you should go is since What's New in Kotlin 1.3 on the official Kotlin site. It contains a complete list of all new features introduced in Kotlin 1.3.

If you find the official list of changes too dry for your taste, you may prefer Todd Ginsberg's list of additions and changes that came with Kotlin 1.3. It has easy-to-follow examples and goes into more detail when I cover Kotlin 1.3's experimental features. Remember that these features are designated as experimental – do not use them in production code!

Kotlin 1.3's biggest change is support for coroutine, and you are likely to want more reading material. The official tutorial lives on kotlinx.coroutine's GitHub repository, and it covers not only the basics, but additional topics like using coroutines for UI programming and reactive flows.

And finally, the topic of coroutines is so great that it could have its own book. Fortunately for you, we wrote it! Kotlin Coroutines by Tutorials introduces you to asynchronous programming in Kotlin by applying coroutines to common Android programming problems.


Source link