<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sebastian Aigner</title>
    <description>The latest articles on DEV Community by Sebastian Aigner (@sebastianaigner).</description>
    <link>https://dev.to/sebastianaigner</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F26006%2F58280da5-1e32-4986-be77-79297aaf1175.jpg</url>
      <title>DEV Community: Sebastian Aigner</title>
      <link>https://dev.to/sebastianaigner</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sebastianaigner"/>
    <language>en</language>
    <item>
      <title>Idiomatic Kotlin: Solving Advent of Code Puzzles, Passport Validation</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Wed, 01 Sep 2021 14:52:59 +0000</pubDate>
      <link>https://dev.to/kotlin/idiomatic-kotlin-solving-advent-of-code-puzzles-passport-validation-1425</link>
      <guid>https://dev.to/kotlin/idiomatic-kotlin-solving-advent-of-code-puzzles-passport-validation-1425</guid>
      <description>&lt;p&gt;Today in “Idiomatic Kotlin”, we’re looking at &lt;a href="https://adventofcode.com/2020/day/4"&gt;day 4 of the Advent of Code 2020 challenges&lt;/a&gt;, in which we tackle a problem that feels as old as programming itself: input sanitization and validation.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/-kltG4Ztv1s"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 4. Passport processing
&lt;/h2&gt;

&lt;p&gt;We need to build a passport scanner that, given a batch of input text, can count how many passports are &lt;em&gt;valid.&lt;/em&gt; You can find the complete task description at &lt;a href="https://adventofcode.com/2020/day/4*"&gt;https://adventofcode.com/2020/day/4&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Like many challenges, we first inspect our input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
byr:1937 iyr:2017 cid:147 hgt:183cm

iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
hcl:#cfa07d byr:1929

hcl:#ae17e1 iyr:2013
eyr:2024
ecl:brn pid:760753108 byr:1931
hgt:179cm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The input is a batch of travel documents in a text file, separated by blank lines. Each &lt;em&gt;passport&lt;/em&gt; is represented as a sequence of key-colon-value pairs separated by spaces or newlines. &lt;em&gt;Our&lt;/em&gt; challenge is finding out how many passports are valid. For part one, “valid” means that they need to have all the required fields outlined by the security personnel: &lt;code&gt;byr&lt;/code&gt;, &lt;code&gt;iyr&lt;/code&gt;, &lt;code&gt;eyr&lt;/code&gt;, &lt;code&gt;hgt&lt;/code&gt;, &lt;code&gt;hcl&lt;/code&gt;, &lt;code&gt;ecl&lt;/code&gt; and &lt;code&gt;pid&lt;/code&gt; (we conveniently ignore their request to validate the &lt;code&gt;cid&lt;/code&gt; field).&lt;/p&gt;

&lt;h2&gt;
  
  
  Solving Day 4, Part 1
&lt;/h2&gt;

&lt;p&gt;Like many challenges, we start by reading our puzzle input as text and trim off any extraneous whitespace at the beginning and the end of the file. As per the description, passports are always separated by blank lines. A blank line is just two “returns”, or newlines, in a row, so we’ll use this to split our input string into the individual passports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;passports&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"src/day04/input.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readText&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"\r\n\r\n"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Note that depending on your operating system, the line separator in text files is different: On Windows, it is &lt;code&gt;\r\n&lt;/code&gt;, on Linux and macOS, it’s &lt;code&gt;\n&lt;/code&gt;. Kotlin’s &lt;code&gt;split&lt;/code&gt; method takes an arbitrary number of delimiters, allowing us to cover both cases directly.)&lt;/p&gt;

&lt;p&gt;We now have a list of passport strings. However, working with lists of raw strings can quickly get confusing. Let’s use Kotlin’s expressive type system to improve the situation and encapsulate the string in a very basic &lt;code&gt;Passport&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then just map the results of our split-up input to &lt;code&gt;Passport&lt;/code&gt; objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// . . .&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the problem description, we remember that key-value pairs are either separated by spaces or newlines within a single passport. Therefore, to get the individual pairs, we once again split our input. The delimiters, in this case, are either a space or one of the newline sequences.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;hasAllRequiredFields&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fieldsWithValues&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"\n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"\r\n"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then extract the key from each passport entry. We can do so by mapping our combined &lt;code&gt;fieldsWithValues&lt;/code&gt; to &lt;em&gt;only&lt;/em&gt; the substring that comes before the colon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;hasAllRequiredFields&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fieldsWithValues&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"\n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"\r\n"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fieldNames&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldsWithValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substringBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fieldNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;containsAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requiredFields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of our function will be whether the &lt;code&gt;fieldNames&lt;/code&gt; we extracted contain all required fields. The &lt;code&gt;requiredFields&lt;/code&gt; collection can be taken directly from the problem statement and translated into a list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;requiredFields&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"byr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"iyr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"eyr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hgt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hcl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ecl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"pid"&lt;/span&gt; &lt;span class="cm"&gt;/*"cid"*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To calculate our final number, and get our first gold star for the challenge, we need to count the passports for which our function &lt;code&gt;hasAllRequiredFields&lt;/code&gt; returns true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;hasAllRequiredFields&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, we have successfully solved the first part of the challenge and can set our sights on the next star in our journey.&lt;/p&gt;

&lt;p&gt;Find the full code for the first part of the challenge on &lt;a href="https://github.com/kotlin-hands-on/advent-of-code-2020/blob/master/src/day04/day4_1.kt"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solving Day 4, Part 2
&lt;/h2&gt;

&lt;p&gt;In part two of the challenge, we also need to ensure that each field on the passport contains a valid value. We are given an additional list of rules to accomplish this task, which you can again find in the &lt;a href="https://adventofcode.com/2020/day/4"&gt;problem description&lt;/a&gt;. Years need to fall into specific ranges, as does a person's height depending on the unit of measurement. Colors need to come from a prespecified list or follow certain patterns, and numbers must be correctly formatted.&lt;/p&gt;

&lt;h3&gt;
  
  
  A refactoring excursion
&lt;/h3&gt;

&lt;p&gt;Before we start building the solution for part 2, let’s briefly reflect on our code and find possible changes that will make adding this functionality easier for us. At this point in the challenge, we &lt;em&gt;know&lt;/em&gt; that our &lt;code&gt;Passport&lt;/code&gt; class will need access to the different field names and their associated values. The classical data structure to store such kind of associative-dictionary information is a map. Let’s refactor our code to store passport information in a map instead of a string.&lt;/p&gt;

&lt;p&gt;Because turning an input string into a map is still a process that’s associated with the &lt;code&gt;Passport&lt;/code&gt;, I like encapsulating such logic in a companion object “factory” function. In this case, we can aptly call it &lt;code&gt;fromString&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The implementation for &lt;code&gt;fromString&lt;/code&gt; partially reuses the normalization logic we had previously used in the first part of this challenge and expands it to create a map directly via Kotlin’s &lt;code&gt;&lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/associate.html"&gt;associate&lt;/a&gt;&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fieldsAndValues&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"\n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"\r\n"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;map&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldsAndValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;associate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;Passport&lt;/code&gt; object now encapsulates a map of string keys and string values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interestingly enough, this change makes the implementation of the first part of our challenge trivial. We can simply check that the key set of our map contains all required fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;hasAllRequiredFields&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;containsAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requiredFields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Returning to solving part 2
&lt;/h3&gt;

&lt;p&gt;For the second part of the challenge, we consider a passport valid if it contains all the required fields and has values that correspond to the official rules.&lt;/p&gt;

&lt;p&gt;To ensure that all fields have valid values, we can use the &lt;code&gt;all&lt;/code&gt; function to assert that a predicate holds true for every single key-value pair in our map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;hasValidValues&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can distinguish the different types of fields using a &lt;code&gt;when&lt;/code&gt; expression. In this first step, we distinguish the different cases based on the keys in our map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each key we know gets a branch in this when statement. They all need to return a boolean value – &lt;code&gt;true&lt;/code&gt; if the field is okay, &lt;code&gt;false&lt;/code&gt; if the field violates the rules. The surrounding &lt;code&gt;all&lt;/code&gt; predicate will then use those results to determine whether the passport as a whole is valid.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;byr&lt;/code&gt; (Birth Year), &lt;code&gt;iyr&lt;/code&gt; (Issue Year), and &lt;code&gt;eyr&lt;/code&gt; (Expiration Year) fields all require their value to be a 4-digit number falling into a particular range:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="s"&gt;"byr"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toIntOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;2002&lt;/span&gt;
&lt;span class="s"&gt;"iyr"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toIntOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;2010&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;2020&lt;/span&gt;
&lt;span class="s"&gt;"eyr"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toIntOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;2030&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that our combined use of &lt;code&gt;toIntOrNull&lt;/code&gt; together with the infix function &lt;code&gt;in&lt;/code&gt; allows us to discard any non-numeric values, and ensure that they fall in the correct range.&lt;/p&gt;

&lt;p&gt;We can apply a very similar rule to the &lt;code&gt;pid&lt;/code&gt; (Passport ID) field. We ensure that the length of the value is correct and ensure that all characters belong to the set of digits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="s"&gt;"pid"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Char&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;isDigit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Validating &lt;code&gt;ecl&lt;/code&gt; (eye color) just requires us to check whether the input is in a certain set of values, similar to the first part of our challenge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="s"&gt;"ecl"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;setOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"amb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"blu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"brn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"gry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"grn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hzl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"oth"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we have two more fields to validate: &lt;code&gt;hgt&lt;/code&gt; (Height) and &lt;code&gt;hcl&lt;/code&gt; (Hair Color). Both of them are a bit more tricky. Let’s look at the &lt;code&gt;hgt&lt;/code&gt; field first.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;hgt&lt;/code&gt; (Height) field can contain a measurement either in centimeters or inches. Depending on the unit used, different values are allowed. Thankfully, both “cm” and “in” are two-character suffixes. This means we can again use Kotlin’s &lt;code&gt;when&lt;/code&gt; function, grab the last two characters in the field value and differentiate the validation logic for centimeters and inches. Like our other number-validation logic, we parse the integer and check whether it belongs to a specific range. To do so, we also remove the unit suffix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="s"&gt;"hgt"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;takeLast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"cm"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeSuffix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cm"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toIntOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;193&lt;/span&gt;
    &lt;span class="s"&gt;"in"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeSuffix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toIntOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;76&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last field to validate is &lt;code&gt;hcl&lt;/code&gt; (Hair Color), which expects a &lt;code&gt;#&lt;/code&gt; followed by exactly six hexadecimal digits – digits from &lt;code&gt;0&lt;/code&gt; through &lt;code&gt;9&lt;/code&gt;, and &lt;code&gt;a&lt;/code&gt; through &lt;code&gt;f&lt;/code&gt;. While Kotlin can parse base-16 numbers, we can use this case to show off the sledgehammer method for validating patterns – regular expressions. Those can be defined as Kotlin strings and converted using the &lt;code&gt;toRegex&lt;/code&gt; function. Triple-quoted strings can help with escape characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="s"&gt;"hcl"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt; &lt;span class="s"&gt;"""#[0-9a-f]{6}"""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toRegex&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our hand-crafted pattern matches exactly one hashtag, then six characters from the group of &lt;code&gt;0&lt;/code&gt; through &lt;code&gt;9&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt; through &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As a short aside for performance enthusiasts: &lt;code&gt;toRegex&lt;/code&gt; is a relatively expensive function, so it may be worth moving this function call into a constant. The same also applies to the set used in the validation for &lt;code&gt;ecl&lt;/code&gt; – currently, it is initialized on each test.&lt;/p&gt;

&lt;p&gt;Because the whole &lt;code&gt;when&lt;/code&gt;-block is used as an expression, we need to ensure that all possible branches are covered. In our case, that just means adding an &lt;code&gt;else&lt;/code&gt; branch, which simply returns &lt;code&gt;true&lt;/code&gt; – just because a passport has a field we don’t know about doesn’t mean it can’t still be valid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, we have covered every rule outlined to us by the problem statement. To get our reward, we can now just count the passports that contain all required fields and have valid values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;partTwo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasAllRequiredFields&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasValidValues&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We end up with a resulting number, which we can exchange for the second star. We’re clear for boarding our virtual flight. Though this was probably not the last challenge that awaits us…&lt;/p&gt;

&lt;p&gt;Find the complete solution for the second part of the challenge on &lt;a href="https://github.com/kotlin-hands-on/advent-of-code-2020/blob/master/src/day04/day4.kt"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For today’s challenge, we came up with an elegant solution to validate specific string information, which we extracted using utility functions offered by the Kotlin standard library. As the challenge continued, we reflected on our code, identified more fitting data structures, and changed our logic to accommodate it. Using Kotlin’s &lt;code&gt;when&lt;/code&gt; statement, we were able to keep the validation logic concise and all in one place. We saw multiple different ways of how to validate input – working with ranges, checking set membership, or matching a particular regular expression, for example.&lt;/p&gt;

&lt;p&gt;Many real-world applications have similar requirements for input validation. Hopefully, some of the tips and tricks you’ve seen in the context of this little challenge will also be helpful when you need to write some validation logic on your own.&lt;/p&gt;

&lt;p&gt;To continue puzzling yourself, check out &lt;a href="https://adventofcode.com/"&gt;adventofcode.com&lt;/a&gt;, whose organizers kindly permitted us to use their problem statements for this series.&lt;/p&gt;

&lt;p&gt;If you want to see more solutions for Advent of Code challenges in the form of videos, subscribe to our &lt;a href="https://www.youtube.com/kotlin"&gt;YouTube channel&lt;/a&gt; and hit the bell to get notified when we continue our idiomatic journey. More puzzle solutions are coming your way!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>adventofcode</category>
      <category>codenewbie</category>
      <category>100daysofcode</category>
    </item>
    <item>
      <title>Exploring Kotlin Lists in 2021</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Thu, 08 Jul 2021 14:46:58 +0000</pubDate>
      <link>https://dev.to/kotlin/exploring-kotlin-lists-in-2021-2gi</link>
      <guid>https://dev.to/kotlin/exploring-kotlin-lists-in-2021-2gi</guid>
      <description>&lt;p&gt;This blog post accompanies a video from our &lt;strong&gt;YouTube series&lt;/strong&gt; which you can find on our &lt;a href="https://kotl.in/video" rel="noopener noreferrer"&gt;Kotlin YouTube channel&lt;/a&gt;, or &lt;strong&gt;watch here&lt;/strong&gt; directly!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/CDWy16UDeLQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today, we're talking all about lists!&lt;/strong&gt; Lists are the most popular collection type in Kotlin for a good reason, and we’ll find out why together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lists
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What’s a list?
&lt;/h3&gt;

&lt;p&gt;If you've written Kotlin code before, you've definitely seen a list – they're collections of ordered elements, where each element is accessible via an index. As such, they're one of the basic building blocks for a lot of Kotlin code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating lists
&lt;/h3&gt;

&lt;p&gt;If you’re creating lists on your own, you’re most likely using the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/list-of.html" rel="noopener noreferrer"&gt;&lt;code&gt;listOf&lt;/code&gt;&lt;/a&gt; function, which takes a variable number of arguments, and those become the elements of your list. Even in this blog post series, we've created a list like that about a hundred times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 3, 4, 5]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A little lesser known is the ability to create lists via the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list.html" rel="noopener noreferrer"&gt;&lt;code&gt;List&lt;/code&gt;&lt;/a&gt; constructor function. Here, we pass two parameters – the &lt;code&gt;size&lt;/code&gt; of the list, and an &lt;code&gt;init&lt;/code&gt; function that creates each of the elements in our list. That function we pass gets the element index as its parameter, which we can use to adjust the item content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"No. $idx"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// [No. 0, No. 1, No. 2, No. 3, No. 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, lists can come from other places as well: types like collections, iterables, and others often feature a &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/to-list.html" rel="noopener noreferrer"&gt;&lt;code&gt;toList&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;For example, in the case of a string, we get a list of its characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="s"&gt;"word-salad"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// [w, o, r, d, -, s, a, l, a, d]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Given a map of placements and the associated medals, we can call &lt;code&gt;toList&lt;/code&gt; on that to get a list of key-value pairs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;mapOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="s"&gt;"Gold"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="s"&gt;"Silver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="s"&gt;"Bronze"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// [(1, Gold), (2, Silver), (3, Bronze)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sequences, ranges, and progressions behave similarly. They materialize their values, and put them in a list when calling &lt;code&gt;toList&lt;/code&gt;. As an example, we can consider a random sequence of numbers, or the inclusive integer range from zero to ten:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;generateSequence&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nextInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;takeIf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// [73, 77, 69, 79, 71, 64]&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An extra case worth mentioning is calling &lt;code&gt;toList&lt;/code&gt; on something that already is a list. This creates brand-new copy of the original list. We can see this in the following example, where we create a mutable list with a few numbers. By calling &lt;code&gt;toList&lt;/code&gt;, we obtain a new working copy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;list&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;otherList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [5, 2, 3]&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otherList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, when the original list is changed, the working copy we just created does not contain any of the changes applied to the original collection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing list items
&lt;/h3&gt;

&lt;p&gt;To get items out of our lists, we have multiple options. The most basic way of doing so is using the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/get.html" rel="noopener noreferrer"&gt;&lt;code&gt;get&lt;/code&gt;&lt;/a&gt; function, together with an index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;myList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🍔"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🌭"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🍕"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 🌭&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if you ever type out &lt;code&gt;.get&lt;/code&gt; manually, you’ll see that IntelliJ IDEA already gives you the helpful hint to use some much more popular syntactic sugar for it – the indexed access operator, denoted by the brackets with an index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// 🌭&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are also some additional flavors of the &lt;code&gt;get&lt;/code&gt; function which we can explore. Two of those that come to mind are &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/get-or-else.html" rel="noopener noreferrer"&gt;&lt;code&gt;getOrElse&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/get-or-null.html" rel="noopener noreferrer"&gt;&lt;code&gt;getOrNull&lt;/code&gt;&lt;/a&gt;. They help us handle cases where we might be accessing an index that falls out of bounds (which can either be a negative index, or an index that’s larger than the last index in our collection.)&lt;/p&gt;

&lt;p&gt;Using the default indexed access causes an &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-index-out-of-bounds-exception/" rel="noopener noreferrer"&gt;exception&lt;/a&gt; when provided a parameter that's out of bounds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;// Index 3 out of bounds for length 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/get-or-null.html" rel="noopener noreferrer"&gt;&lt;code&gt;getOrNull&lt;/code&gt;&lt;/a&gt; to short-circuit our return value to &lt;code&gt;null&lt;/code&gt;. Alternatively, we can use &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/get-or-else.html" rel="noopener noreferrer"&gt;&lt;code&gt;getOrElse&lt;/code&gt;&lt;/a&gt; to compute a default value to be used instead. The default value is computed based on a passed lambda, which also receives the index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;myList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🍔"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🌭"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🍕"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// null&lt;/span&gt;

&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrElse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"There's no index $it!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="s"&gt;"😔"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// There's no index 3!&lt;/span&gt;
&lt;span class="c1"&gt;// 😔&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These special functions are only necessary to work with indexes that might fall out of bounds, though. &lt;a href="https://kotlinlang.org/docs/null-safety.html" rel="noopener noreferrer"&gt;Nullability&lt;/a&gt;, for example, is handled the same way as you would in any other situation in Kotlin: using the power of the Elvis operator, smart-casts and friends.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;listOfNullableItems&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listOfNullableItems&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Slicing
&lt;/h3&gt;

&lt;p&gt;Of course, we can go beyond getting individual items out of our list. Because a list is a collection like any other, we have access to the same &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/take.html" rel="noopener noreferrer"&gt;&lt;code&gt;take&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/drop.html" rel="noopener noreferrer"&gt;&lt;code&gt;drop&lt;/code&gt;&lt;/a&gt; functions that were introduced in the &lt;em&gt;&lt;a href="https://dev.to/kotlin/diving-into-kotlin-collections-587o"&gt;Diving into Kotlin collections&lt;/a&gt;&lt;/em&gt; post.&lt;/p&gt;

&lt;p&gt;But lists have a special way of retrieving multiple items - the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/slice.html" rel="noopener noreferrer"&gt;&lt;code&gt;slice&lt;/code&gt;&lt;/a&gt; function!&lt;/p&gt;

&lt;p&gt;When we give this function a bunch of indexes, it returns the elements at those places in our collection. In this example, we’re passing a list with index &lt;code&gt;0, 2, 4&lt;/code&gt;, and get those items from our list of letters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;myList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"e"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// [a, c, e]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of writing out all the indices by hand, we could also use &lt;code&gt;IntRange&lt;/code&gt;s or progressions to specify the indexes. For example, we could request “all items from 0 through 3”, or specify a custom step-size of 2. We could even pull out some items in reverse order, if we create a progression that uses &lt;code&gt;downTo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [a, b, c, d]&lt;/span&gt;

&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastIndex&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [a, c, e]&lt;/span&gt;

&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;downTo&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [c, b, a]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you may suspect, this &lt;em&gt;list&lt;/em&gt; of list features is not quite exhaustive – as always, there’s some more to explore even on this subject. But let’s put that on the back burner for a bit, and move on to a special kind of list – it's time to talk about &lt;em&gt;mutable lists&lt;/em&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Mutable Lists
&lt;/h2&gt;

&lt;p&gt;What's so special about mutable lists? Well, you can &lt;em&gt;mutate&lt;/em&gt; them! That, of course, doesn’t mean that these lists will turn into zombies (🧟‍♂️), but that you can change their content. If we consult an excerpt of a class hierarchy, we can see that &lt;code&gt;MutableList&lt;/code&gt; specializes &lt;code&gt;List&lt;/code&gt;, meaning everything we’ve learned about lists so far also works for their mutable counterpart, plus some extra functionality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrg0js7pl6435klg2gm0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrg0js7pl6435klg2gm0.png" alt="list-specialization"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;It's precisely that extra functionality that we’re interested in right now!&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating mutable lists
&lt;/h3&gt;

&lt;p&gt;Once again, mutable lists are commonly created via the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/mutable-list-of.html" rel="noopener noreferrer"&gt;&lt;code&gt;mutableListOf&lt;/code&gt;&lt;/a&gt; function, with a bunch of values as arguments. And, wherever you were able to find a &lt;code&gt;toList&lt;/code&gt; method, as discussed previously, you’ll probably also find a &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/to-mutable-list.html" rel="noopener noreferrer"&gt;&lt;code&gt;toMutableList&lt;/code&gt;&lt;/a&gt;. That also includes other lists and mutable lists – where you’ll get a fresh copy when calling &lt;code&gt;toMutableList&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 3]&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toMutableList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]&lt;/span&gt;

&lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toMutableList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add / Remove / Update
&lt;/h3&gt;

&lt;p&gt;Let's move on to the core of this subject – the ability to change content. That starts with adding something to the collection. If we want to add an extra number to the end of our mutable list we can do so via the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/add.html" rel="noopener noreferrer"&gt;&lt;code&gt;add&lt;/code&gt;&lt;/a&gt; function, or by using the &lt;code&gt;+=&lt;/code&gt; operator shorthand, both of which append an item to the end of the list.&lt;/p&gt;

&lt;p&gt;If we know &lt;em&gt;where&lt;/em&gt; in the collection we want our item to go, the &lt;code&gt;add&lt;/code&gt; function also accepts an index, which inserts the new element at that position and moves the surrounding elements to accommodate it. In the same way, we can also add a whole other collection to our mutable list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 3, 4, 4]&lt;/span&gt;

&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 10, 3, 4, 4]&lt;/span&gt;

&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 10, 3, 4, 4, 5, 6, 7]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re of course not constrained to just adding elements to our list – we can also remove them. If we know what element we want to get rid of, we can do that via the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/remove.html" rel="noopener noreferrer"&gt;&lt;code&gt;remove&lt;/code&gt;&lt;/a&gt; function or the &lt;code&gt;-=&lt;/code&gt; operator shorthand, which removes from our collection &lt;em&gt;a single instance&lt;/em&gt; of the element we provide. In this example, after calling -= and &lt;code&gt;remove&lt;/code&gt;, we got rid of two of the 3s in our original collection – because each invocation removed one of them.&lt;/p&gt;

&lt;p&gt;Alternatively, we can also pass the &lt;code&gt;-=&lt;/code&gt; operator a collection of elements. In this case, the operator acts as a shorthand for the &lt;code&gt;removeAll&lt;/code&gt; function. Here, it looks at every element in the collection we pass, and &lt;em&gt;removes all instances of them&lt;/em&gt; in our original, mutable collection. (This is an important distinction to make!) So, by passing 1 and 4 as a collection, we remove &lt;em&gt;all instances&lt;/em&gt; of those numbers from our mutable list, and we’re left with only 2 and 3 at the end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 3, 4, 4, 4]&lt;/span&gt;

&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we know the index where we want to kick an item out, we use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/remove-at.html" rel="noopener noreferrer"&gt;&lt;code&gt;removeAt&lt;/code&gt;&lt;/a&gt; function instead. For example, we could remove the second element in our list, which resides at index 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 3, 3, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To update an item, we most commonly use the &lt;a href="https://kotlinlang.org/docs/operator-overloading.html#indexed-access-operator" rel="noopener noreferrer"&gt;&lt;em&gt;indexed access operator&lt;/em&gt;&lt;/a&gt; – so the brackets – together with an assignment. That one calls the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html" rel="noopener noreferrer"&gt;&lt;code&gt;set&lt;/code&gt;&lt;/a&gt; function with that index and element under the hood, and switches out the item at the specified index – in this case, trading a "b" for an "a".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"e"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"a"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [a, a, c, d, e]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fill and Clear
&lt;/h3&gt;

&lt;p&gt;In certain situations, we might want to turn all elements of our list into the same element – like zeroing out a buffer before reusing it. This is something we can do using the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/fill.html" rel="noopener noreferrer"&gt;&lt;code&gt;fill&lt;/code&gt;&lt;/a&gt; function, which replaces each element with the same value we specify. If we look at a list of fruits, for example, and suddenly realize that all of them are really just sugar, we use fill to replace them with candy (🍬). While that metaphor may not be &lt;em&gt;entirely scientifically accurate&lt;/em&gt;, it's tasty nonetheless!&lt;/p&gt;

&lt;p&gt;And when we want to wipe our collection clean, the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/clear.html" rel="noopener noreferrer"&gt;&lt;code&gt;clear&lt;/code&gt;&lt;/a&gt; function can help with removing all elements from a collection – in our case, getting rid of all the candy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fruits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🍉"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🍊"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🥝"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// wait, it's all sugar?&lt;/span&gt;
&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🍬"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🍬, 🍬, 🍬]&lt;/span&gt;

&lt;span class="c1"&gt;// ... nom nom&lt;/span&gt;
&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// []&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perhaps unsurprisingly, mutable lists grow and shrink automatically to accommodate all your items, so you can have an arbitrary number of elements in your collection. This might be obvious, but it’s so darn convenient, so I figured I’d mention it. The things we take for granted!&lt;/p&gt;

&lt;h3&gt;
  
  
  In-place modifications
&lt;/h3&gt;

&lt;p&gt;Thinking back to some of the previous entries of this series, we’ve seen a number of neat functions which we wouldn’t want to miss for mutable collections either – things like &lt;code&gt;sorted&lt;/code&gt;, &lt;code&gt;shuffled&lt;/code&gt;, and &lt;code&gt;reversed&lt;/code&gt;. However, those don’t modify the original collection.&lt;/p&gt;

&lt;p&gt;Luckily for us, these functions also have a mutable counterpart. So, when we want to sort, shuffle, or reverse a mutable list in place – instead of creating a new, separate copy with the effects applied – we use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sort.html" rel="noopener noreferrer"&gt;&lt;code&gt;sort()&lt;/code&gt;&lt;/a&gt; instead of &lt;code&gt;sorted()&lt;/code&gt;, &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/shuffle.html" rel="noopener noreferrer"&gt;&lt;code&gt;shuffle()&lt;/code&gt;&lt;/a&gt; instead of &lt;code&gt;shuffled()&lt;/code&gt;, and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reverse.html" rel="noopener noreferrer"&gt;&lt;code&gt;reverse()&lt;/code&gt;&lt;/a&gt; instead of &lt;code&gt;reversed()&lt;/code&gt; functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;list&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shuffled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [3, 1, 4, 1, 5, 9]&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toMutableList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [5, 1, 1, 3, 4, 9]&lt;/span&gt;

&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 1, 3, 4, 5, 9]&lt;/span&gt;

&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [9, 5, 4, 3, 1, 1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mutable lists also offer the possibility to remove or keep &lt;em&gt;all&lt;/em&gt; elements that fulfill a certain predicate. The &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/remove-all.html" rel="noopener noreferrer"&gt;&lt;code&gt;removeAll&lt;/code&gt;&lt;/a&gt; function can remove all elements that match the predicate we specify. Let’s say we’re not a fan of small numbers in our collection, and only want to keep numbers that are 5 or above – &lt;code&gt;removeAll&lt;/code&gt; helps us do exactly that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;numbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeAll&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [5, 9]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/retain-all.html" rel="noopener noreferrer"&gt;&lt;code&gt;retainAll&lt;/code&gt;&lt;/a&gt; function is the opposite, and only keeps those elements in the mutable list that match. If we want to retain every character in our collection that is a letter, we do that with the &lt;code&gt;retainAll&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;letters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'5'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retainAll&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isLetter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [a, b, d]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might feel a bit familiar to you, and rightfully so, because these are essentially the mutating equivalents of the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter.html" rel="noopener noreferrer"&gt;&lt;code&gt;filter&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-not.html" rel="noopener noreferrer"&gt;&lt;code&gt;filterNot&lt;/code&gt;&lt;/a&gt; functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Views on Lists
&lt;/h3&gt;

&lt;p&gt;The last topic on today’s agenda is views on lists. That name already hints at what they allow us to do – they allow us to look at the elements in our list from a different perspective – let’s see what that means.&lt;/p&gt;

&lt;p&gt;Let’s assume we have a collection of fruits. To create a view, we can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/sub-list.html" rel="noopener noreferrer"&gt;&lt;code&gt;subList&lt;/code&gt;&lt;/a&gt; function, which takes a beginning and end index, which determines which elements should be “visible” in the view. By having a look at an example sublist, we can see that it contains the elements from our original collections based on the indices we specify (with the upper bound being exclusive):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fruits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🍉"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🍊"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🥝"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🍏"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;sub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🍊, 🥝, 🍏]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because this is only a &lt;em&gt;view&lt;/em&gt;, and not a copy of our original collection, changes are automatically visible. That means if we change the orange to a banana in the underlying &lt;code&gt;fruits&lt;/code&gt; list, then our sublist will reflect that change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"🍌"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🍌, 🥝, 🍏]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What may be even more interesting is that this sublist is in itself mutable, as well! If we change the green apple in our sublist to a pineapple, and have a look at our original fruits collection again, we see that the change is visible from here as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"🍍"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🍉, 🍌, 🥝, 🍍]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, we can use the fill function which we’ve learned about earlier to turn an interval inside of our fruit-list back into candy, again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🍬"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🍉, 🍬, 🍬, 🍬]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To reiterate; all of that works because these aren’t two different collections – there is only one collection, and  &lt;code&gt;subList&lt;/code&gt; has just given us a different perspective on that list!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An important note on the topic of sublists:&lt;/strong&gt; They are only well-defined as long as the underlying, original list is &lt;em&gt;not structurally changed&lt;/em&gt;. Changes affecting the size of the list, for example, automatically cause any views that were previously returned by invoking &lt;code&gt;subList&lt;/code&gt; to have undefined behavior.&lt;/p&gt;

&lt;p&gt;For a common case, which is looking at a list backwards, the Kotlin standard library also comes with the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/as-reversed.html" rel="noopener noreferrer"&gt;&lt;code&gt;asReversed&lt;/code&gt;&lt;/a&gt; function. It provides a backwards view of the underlying list. Once again, changes made in the view are visible in the original collection, and vice versa. As you can see in the following example, turning the orange into a banana in our original list also changes what we see in the reversed view. Altering it back to a pineapple via our reversed view also alters our original mutable list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fruits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🍉"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🍊"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🥝"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🍏"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;stiurf&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asReversed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stiurf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🍏, 🥝, 🍊, 🍉]&lt;/span&gt;

&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"🍌"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stiurf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🍏, 🥝, 🍌, 🍉]&lt;/span&gt;

&lt;span class="n"&gt;stiurf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"🍍"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🍉, 🍍, 🥝, 🍏]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These types of “views” are actually available for non-mutable lists, as well, and allow you to pass around different sub-selections of your collections without having to create new copies every time – however, this seemed like a topic that would be nicer to illustrate with the mutable variant, to drive the point home that there really is only one underlying collection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;With that, we have reached the end of today’s expedition! I hope some of the stuff you’ve seen today is helping you strengthen your understanding of Kotlin lists. When you’re  writing Kotlin code the next time, see if you can apply some of the stuff we’ve talked about today – whether it’s slicing a collection, using sub-lists, or handling out-of-bounds situations for lists elegantly with the &lt;code&gt;getOrNull&lt;/code&gt; and &lt;code&gt;getOrElse&lt;/code&gt; functions.&lt;/p&gt;

&lt;p&gt;If you’ve learned something new, and want to see more like this, make sure to &lt;a href="https://dev.to/kotlin"&gt;follow us here on dev.to&lt;/a&gt;, and check out some of the interesting content we publish on &lt;a href="http://kotl.in/video" rel="noopener noreferrer"&gt;our official YouTube channel&lt;/a&gt;, as well!&lt;/p&gt;

&lt;p&gt;Now, it’s time for all of you to go and explore some more Kotlin! Take care, and see you in the next one!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>programming</category>
      <category>android</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Advanced Kotlin Collection Functionality</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Mon, 14 Jun 2021 17:49:10 +0000</pubDate>
      <link>https://dev.to/kotlin/advanced-kotlin-collection-functionality-5e90</link>
      <guid>https://dev.to/kotlin/advanced-kotlin-collection-functionality-5e90</guid>
      <description>&lt;p&gt;This blog post accompanies a video from our &lt;strong&gt;YouTube series&lt;/strong&gt; which you can find on our &lt;a href="https://kotl.in/video" rel="noopener noreferrer"&gt;Kotlin YouTube channel&lt;/a&gt;, or &lt;strong&gt;watch here&lt;/strong&gt; directly!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/N4CpLxGJlq0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Today, we are learning about advanced functions that we can use to work with and manipulate all kinds of Kotlin collections!&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking predicates: &lt;code&gt;any&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt; and &lt;code&gt;all&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s warm up by having a look at a selection of functions that allow us to check conditions for our collection elements.&lt;/p&gt;

&lt;p&gt;They’re called &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/any.html" rel="noopener noreferrer"&gt;&lt;code&gt;any&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/none.html" rel="noopener noreferrer"&gt;&lt;code&gt;none&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/all.html" rel="noopener noreferrer"&gt;&lt;code&gt;all&lt;/code&gt;&lt;/a&gt;. Each of them takes a &lt;em&gt;predicate&lt;/em&gt; – so a function that returns &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; – and checks whether the collection fits this predicate.&lt;/p&gt;

&lt;p&gt;Let’s say we have a group of friends (which is really just a &lt;code&gt;List&amp;lt;Person&amp;gt;&lt;/code&gt;, each featuring a &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt;, and maybe a &lt;code&gt;driversLicense&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;driversLicense&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;friendGroup&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Jo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hay"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we want to check if the group can travel by car, we want to check if &lt;em&gt;any&lt;/em&gt; of them have a driver's license – so we use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/any.html" rel="noopener noreferrer"&gt;&lt;code&gt;any&lt;/code&gt;&lt;/a&gt; function. It returns &lt;code&gt;true&lt;/code&gt; if there is &lt;em&gt;at least one element&lt;/em&gt; in our collection for which the predicate returns &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;groupCanTravel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;friendGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driversLicense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As another example, let’s say we want to check if this group of friends is allowed to enter a club – for this, we would need to make sure that &lt;em&gt;none&lt;/em&gt; of the folks in the group are underage!&lt;/p&gt;

&lt;p&gt;Here, we can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/none.html" rel="noopener noreferrer"&gt;&lt;code&gt;none&lt;/code&gt;&lt;/a&gt; function, which only returns &lt;code&gt;true&lt;/code&gt; when there is &lt;em&gt;not a single element in our collection&lt;/em&gt; that holds true for our predicate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;groupGetsInClub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;friendGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;none&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The third function in the bunch is the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/all.html" rel="noopener noreferrer"&gt;&lt;code&gt;all&lt;/code&gt;&lt;/a&gt; function. At this point, you can probably spot the pattern – &lt;code&gt;all&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt;, if each and every element in our collection matches our predicate. We could use it to check whether all names in our friend group are short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;groupHasShortNames&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;friendGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Predicates for empty collections
&lt;/h3&gt;

&lt;p&gt;While on the topic, let's have a little brain teaser: How do &lt;code&gt;any&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt;, and &lt;code&gt;all&lt;/code&gt; behave for &lt;em&gt;empty collections&lt;/em&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;nobody&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emptyList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// what happens here?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s look at &lt;code&gt;any&lt;/code&gt; first. There is no element that can satisfy the predicate, so it returns &lt;code&gt;false&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;nobody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driversLicense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same goes for &lt;code&gt;none&lt;/code&gt; – there is no function that can violate our predicate, so it returns true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;nobody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;none&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;all&lt;/code&gt; function, however, returns &lt;code&gt;true&lt;/code&gt; with an empty collection. This may surprise you in the first moment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;nobody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this is quite intentional and sound: You can't name an element that &lt;em&gt;violates&lt;/em&gt; the predicate. Therefore, the predicate has to be true for &lt;em&gt;all elements in the collection&lt;/em&gt; – even if there are &lt;em&gt;none&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;This might feel a bit mind-bending to think about at first, but you’ll find that this concept, which is called the &lt;a href="https://en.wikipedia.org/wiki/Vacuous_truth" rel="noopener noreferrer"&gt;vacuous truth&lt;/a&gt;, actually plays very well with checking conditions, and expressing logic in program code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthg07e0ao215ck2lwm1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthg07e0ao215ck2lwm1z.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Collection parts: &lt;code&gt;chunked&lt;/code&gt; and &lt;code&gt;windowed&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;With our brain freshly teased, let’s move on to the next topic, and learn about how to break collections into parts!&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;chunked&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;If we have a collection that just contains a bunch of items, we can cut up the list into individual chunks of a certain size by using the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/chunked.html" rel="noopener noreferrer"&gt;&lt;code&gt;chunked&lt;/code&gt;&lt;/a&gt; function. What we get back is a list of lists, where each element is a _chunk _of our original list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;objects&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🌱"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🚀"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"💡"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🐧"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⚙️"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🤖"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"📚"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// [[🌱, 🚀, 💡], [🐧, ⚙️, 🤖], [📚]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we break our list of random objects (represented with emojis) apart, using a chunk size of 3.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The first &lt;em&gt;element&lt;/em&gt; in our result is in itself a &lt;em&gt;list&lt;/em&gt; which contains our first three objects – &lt;code&gt;[🌱, 🚀, 💡]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The second element is once again a chunk, and contains the three elements that follow after that – &lt;code&gt;[🐧, ⚙️, 🤖]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The last element is also a chunk – but since we ran out of elements to fill it with three items, it only contains the book stack - &lt;code&gt;[📚]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In typical standard library fashion, the &lt;code&gt;chunked&lt;/code&gt; function also provides a little bit of extra power. To immediately transform the chunks we just created, we can apply a &lt;em&gt;transformation function&lt;/em&gt;. For example, we can reverse the order of elements in the resulting lists, without having to do another &lt;code&gt;map&lt;/code&gt; call separately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;// [[💡, 🚀, 🌱], [🤖, ⚙️, 🐧], [📚]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To summarize: the &lt;code&gt;chunked&lt;/code&gt; function cuts our original collection into lists of lists, where each list has the specified size.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;windowed&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;Closely related is the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/windowed.html" rel="noopener noreferrer"&gt;&lt;code&gt;windowed&lt;/code&gt;&lt;/a&gt; function. It also returns a list of lists from our collection. Instead of cutting it up into pieces, however, this function generates a “sliding window” of our collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// [[🌱, 🚀, 💡], [🚀, 💡, 🐧], [💡, 🐧, ⚙️], [🐧, ⚙️, 🤖], [⚙️, 🤖, 📚]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The first window is once again the first three elements – &lt;code&gt;[🌱, 🚀, 💡]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The next window is &lt;code&gt;[🚀, 💡, 🐧]&lt;/code&gt; – we simply “moved” our window of size 3 over by one, which includes some overlap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;windowed&lt;/code&gt; function can also be customized. We can change both &lt;em&gt;window&lt;/em&gt; and &lt;em&gt;step&lt;/em&gt; size, the latter being the number of elements that the window should “slide along” for each step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partialWindows&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// [[🌱, 🚀, 💡, 🐧], [💡, 🐧, ⚙️, 🤖], [⚙️, 🤖, 📚], [📚]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see in the example above, we can also control whether our result should contain &lt;em&gt;partial windows&lt;/em&gt;. This changes the behavior when we’ve reached the end of our input collection, and we’re running out of elements.&lt;/p&gt;

&lt;p&gt;With partial windows enabled, we just &lt;em&gt;keep sliding&lt;/em&gt;, and we get the last elements trickling in, in the form of smaller windows, until we get a window which once again only contains the last element from our input collection – &lt;code&gt;[⚙️, 🤖, 📚], [📚]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;windowed&lt;/code&gt; also allows us to perform an additional transformation at the end, which can modify the individual windows directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;// [[🐧, 💡, 🚀, 🌱], [🤖, ⚙️, 🐧, 💡], [📚, 🤖, ⚙️], [📚]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Un-nesting Collections: Flatten and Flatmap
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;chunked&lt;/code&gt; and &lt;code&gt;windowed&lt;/code&gt; functions, along with some others all return nested collections – lists of lists. What if we want to &lt;em&gt;un-nest&lt;/em&gt; these, turning them back into flat lists of elements? As usual, we do not need to fear, because the standard library has got us covered.&lt;/p&gt;

&lt;p&gt;We can call the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/flatten.html" rel="noopener noreferrer"&gt;&lt;code&gt;flatten&lt;/code&gt;&lt;/a&gt; function on a collection of collections. As you may suspect, the result is a single list of all the elements that were originally contained inside of our nested collections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;objects&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🌱"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🚀"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"💡"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🐧"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⚙️"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🤖"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"📚"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// [🐧, 💡, 🚀, 🌱, 🤖, ⚙️, 🐧, 💡, 📚, 🤖, ⚙️, 📚]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is also a good point to talk about the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/flat-map.html" rel="noopener noreferrer"&gt;&lt;code&gt;flatMap&lt;/code&gt;&lt;/a&gt; function. &lt;code&gt;flatMap&lt;/code&gt; is like a combination of first using &lt;code&gt;map&lt;/code&gt;, and then using &lt;code&gt;flatten&lt;/code&gt; – It takes a lambda which generates a &lt;em&gt;collection&lt;/em&gt; from each of the elements in our input collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;lettersInNames&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Lou"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Cyn"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lettersInNames&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [L, o, u, M, e, l, C, y, n]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, the function that we provide creates a &lt;em&gt;list&lt;/em&gt; for each element in our input collection, containing the letters of the original string. Next, that collection of collections gets flattened. As desired, we end up with a plain list of elements – the list of characters from the names of the original collection.&lt;/p&gt;

&lt;p&gt;If you are doing an operation on a list, which in turn generates a collection for each one of the input elements, consider if &lt;code&gt;flatMap&lt;/code&gt; can help you simplify your code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining collections: &lt;code&gt;zip&lt;/code&gt; and &lt;code&gt;unzip&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;So far, we have always looked at a single collection, and what we can do with it. Let's learn about a way to combine two collections, and create a new one from them – it's time to &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/zip.html" rel="noopener noreferrer"&gt;&lt;code&gt;zip&lt;/code&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;zip&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;Assume we have two collections, where the elements at each index are somehow related. For example, this could be a list of cities in Germany, and we have another list of German license plates that correspond to those cities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;germanCities&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Aachen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Bielefeld"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"München"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;germanLicensePlates&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"AC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"BI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"M"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;germanCities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;germanLicensePlates&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// [(Aachen, AC), (Bielefeld, BI), (München, M)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, by zipping these two collections, we get a &lt;em&gt;list of pairs&lt;/em&gt;, where each pair contains the elements with the same index from the original two collections.&lt;/p&gt;

&lt;p&gt;Metaphorically, this is similar to a zipper on a jacket, where the teeth match up one by one. We zip together the elements of our collection, and we get pairs of each city and its corresponding license plate.&lt;/p&gt;

&lt;p&gt;For an extra bit of flair, we can also call the &lt;code&gt;zip&lt;/code&gt; function using infix notation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;germanCities&lt;/span&gt; &lt;span class="n"&gt;zip&lt;/span&gt; &lt;span class="n"&gt;germanLicensePlates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [(Aachen, AC), (Bielefeld, BI), (München, M)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;zip&lt;/code&gt; can also take a transformation function. We can pass a lambda that receives the values of the individual zipped pairs, and we can apply a transformation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;germanCities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;germanLicensePlates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plate&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;plate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lowercase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;// [(AACHEN, ac), (BIELEFELD, bi), (MÜNCHEN, m)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The &lt;code&gt;unzip&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;The standard library also contains the inverse function, called &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/unzip.html" rel="noopener noreferrer"&gt;&lt;code&gt;unzip&lt;/code&gt;&lt;/a&gt;, which takes a list of pairs, and splits them back into a pair of two separate lists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;citiesToPlates&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;germanCities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;germanLicensePlates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plate&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;plate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lowercase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;cities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;plates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;citiesToPlates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unzip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [AACHEN, BIELEFELD, MÜNCHEN]&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [ac, bi, m]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example above uses a destructuring declaration to easily access both of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;zipWithNext&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;In a way, &lt;code&gt;zipWithNext&lt;/code&gt; is really a specialized case of the &lt;code&gt;windowed&lt;/code&gt; function we got to know today: Instead instead of zipping together two separate lists element by element, this function takes one collection, and zips each of its items with the one that follows it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;random&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zipWithNext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;// [(3, 1), (1, 4), (4, 1), (1, 5), (5, 9), (9, 2), (2, 6), (6, 5), (5, 4)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we're zipping together a list of numbers. If we want to check the “change” – how much the value increments or decrements each step – we can express this quite elegantly using &lt;code&gt;zipWithNext&lt;/code&gt;. We provide a lambda that receives a pair of one number and the one that follows immediately after:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;random&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;changes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zipWithNext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [-2, 3, -3, 4, 4, -7, 4, -1, -1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom aggregations: &lt;code&gt;reduce&lt;/code&gt; and &lt;code&gt;fold&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;We have finally arrived at the &lt;em&gt;grand finale&lt;/em&gt; for this post – functions that help us build custom aggregations.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;reduce&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;Let’s set the scene with a small callback – in the &lt;a href="https://dev.to/kotlin/diving-into-kotlin-collections-587o"&gt;previous post&lt;/a&gt;, we learned about functions like &lt;code&gt;sum&lt;/code&gt;, &lt;code&gt;average&lt;/code&gt;, &lt;code&gt;count&lt;/code&gt;, and functions to receive the minimum and maximum elements inside a collection. All of these &lt;em&gt;reduce&lt;/em&gt; our collection to a single value.&lt;/p&gt;

&lt;p&gt;It's possible that we find ourselves in a situation where there’s no out-of-the-box function for how we want to generate a single value for our collection. For example, we may want to multiply all numbers in a list, instead of summing them.&lt;/p&gt;

&lt;p&gt;In this case, we can rely on the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reduce.html" rel="noopener noreferrer"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; function as a more generic version for aggregating a collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;random&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;multiplicativeAggregate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiplicativeAggregate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 129600&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As seen in the example above, we call the reduce function with a lambda block which receives two parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An accumulator, which has the same type as our collection, and&lt;/li&gt;
&lt;li&gt;An individual item from our collection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The task of the lambda function is to &lt;em&gt;return a new accumulator&lt;/em&gt;. Each invocation, one after the other, receives not only the &lt;em&gt;current element&lt;/em&gt;, but also the &lt;em&gt;result of the previous calculation&lt;/em&gt;, inside the accumulator.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The function starts with the first element of our collection in the accumulator.&lt;/li&gt;
&lt;li&gt;Then it runs our operation – in this example, we multiply the accumulator (which right now is the first number) with the current element (which is the second number).&lt;/li&gt;
&lt;li&gt;We’ve calculated a new value, which will be stored in the accumulator, and used when our function is called once more with the third element&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This cycle repeats, and we continue to gradually build up the final result in our accumulator. One might even say we’re &lt;em&gt;accumulating&lt;/em&gt; that result!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fri4o64h51mzhg2cwe4g2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fri4o64h51mzhg2cwe4g2.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we’ve gone through all the elements in our collection, &lt;code&gt;reduce&lt;/code&gt; returns the final value that’s inside the accumulator.&lt;/p&gt;

&lt;p&gt;As you can see, with &lt;code&gt;reduce&lt;/code&gt;, we can hide a lot of mechanics for aggregating our collection behind one function call, and stay true to Kotlin’s concise nature.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;fold&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;But we can actually go beyond this, and can take this versatility one step further – with the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/fold.html" rel="noopener noreferrer"&gt;&lt;code&gt;fold&lt;/code&gt;&lt;/a&gt; operation. Remember – when we used &lt;code&gt;reduce&lt;/code&gt;, the iteration starts with the first element of our input collection in the accumulator. &lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;fold&lt;/code&gt; function, we get to specify our own accumulator – and in fact, it can even have a different type than the items in our input collection! As an example, we can take a list of words, and multiply the number of their characters together using &lt;code&gt;fold&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fruits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"apple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cherry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"banana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"orange"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;multiplied&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiplied&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 1080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The underlying mechanism is the same – the lambda passed to the &lt;code&gt;fold&lt;/code&gt; function gets called with an accumulator and a value, and calculates a new accumulator. The difference is that we specify the initial value of the accumulator ourselves.&lt;/p&gt;

&lt;p&gt;(&lt;em&gt;Note that we pass &lt;code&gt;1&lt;/code&gt; as an initial value for our accumulator, and not &lt;code&gt;0&lt;/code&gt;. That’s because for multiplication, 1 is the &lt;a href="https://en.wikipedia.org/wiki/Identity_element" rel="noopener noreferrer"&gt;neutral element&lt;/a&gt;&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;fold&lt;/code&gt; and &lt;code&gt;reduce&lt;/code&gt; come in a number of other flavors, as well:&lt;/p&gt;

&lt;p&gt;– the sibling functions &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reduce-right.html" rel="noopener noreferrer"&gt;&lt;code&gt;reduceRight&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/fold-right.html" rel="noopener noreferrer"&gt;&lt;code&gt;foldRight&lt;/code&gt;&lt;/a&gt; change the order of iteration&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reduce-or-null.html" rel="noopener noreferrer"&gt;&lt;code&gt;reduceOrNull&lt;/code&gt;&lt;/a&gt; allows you to work with empty collections without throwing exceptions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/running-fold.html" rel="noopener noreferrer"&gt;&lt;code&gt;runningFold&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/running-reduce.html" rel="noopener noreferrer"&gt;&lt;code&gt;runningReduce&lt;/code&gt;&lt;/a&gt; don’t just return a single value representing the final state of the accumulator, but instead return a list of all the intermediate accumulator values as well.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  That's it!
&lt;/h2&gt;

&lt;p&gt;This concludes my overview of some advanced collection operations in Kotlin – I hope you found this post useful, and have learned something new!&lt;/p&gt;

&lt;p&gt;Maybe you can find a point in your code where a predicate, some zipping, chunking or windowing could come in handy! Or maybe you want to explore by defining your own aggregations functions based on the &lt;code&gt;reduce&lt;/code&gt; or &lt;code&gt;fold&lt;/code&gt; functions.&lt;/p&gt;

&lt;p&gt;To get reminded when new Kotlin content is released, follow us here on &lt;a href="https://dev.to/kotlin"&gt;dev.to/kotlin&lt;/a&gt;, and make sure to follow me on Twitter &lt;a href="https://twitter.com/sebi_io" rel="noopener noreferrer"&gt;@sebi_io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, use this opportunity sure to find the subscribe button and notification bell on our &lt;a href="https://kotl.in/video" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Take care!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>programming</category>
      <category>android</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Tips &amp; tricks for building a game using Compose for Desktop</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Thu, 06 May 2021 13:03:41 +0000</pubDate>
      <link>https://dev.to/kotlin/tips-tricks-for-building-a-game-using-jetpack-compose-for-desktop-266o</link>
      <guid>https://dev.to/kotlin/tips-tricks-for-building-a-game-using-jetpack-compose-for-desktop-266o</guid>
      <description>&lt;p&gt;In the &lt;strong&gt;first part of my blog post series&lt;/strong&gt; about building a small clone of the classic arcade game &lt;a href="https://en.wikipedia.org/wiki/Asteroids_(video_game)" rel="noopener noreferrer"&gt;&lt;strong&gt;Asteroids&lt;/strong&gt;&lt;/a&gt; on top of Jetpack Compose for Desktop, we saw how to implement the main game loop, as well as manage state and draw basic shapes. In this post, we will explore some more details of the game implementation. This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rendering details&lt;/strong&gt; – making sure game objects don't escape our play area, and using a device-independent coordinate system for rendering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Geometry and linear algebra&lt;/strong&gt; – the &lt;em&gt;secret sauce&lt;/em&gt; that makes the space ships fly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frame-independent movement&lt;/strong&gt; – so that our game works consistently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's learn about these topics!&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering: Clipping and Coordinate Systems
&lt;/h2&gt;

&lt;p&gt;In the context of rendering, there are two areas that still need our attention – we need to make sure that our &lt;strong&gt;game objects are constrained to the game surface&lt;/strong&gt;, and we need to make a conscious decision about the &lt;strong&gt;units of the coordinates&lt;/strong&gt; we use to describe the position of a game object. We'll discuss both in this section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clipping
&lt;/h3&gt;

&lt;p&gt;By default, Compose naively draws your objects without any clipping. This means game objects can poke outside the "play surface", which produces a weirdly fourth-wall-breaking effect:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xh0d39znpo8w97djsab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xh0d39znpo8w97djsab.png" alt="game objects escaping the bounds of reality"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We &lt;strong&gt;constrain the game objects to the bounds&lt;/strong&gt; of our play surface by applying &lt;code&gt;Modifier.clipToBounds()&lt;/code&gt; to the &lt;code&gt;Box&lt;/code&gt; which defines our play surface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxHeight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clipToBounds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="c1"&gt;// . . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because all our game elements are drawn as children of this play area &lt;code&gt;Box&lt;/code&gt;, using this modifier causes the rendered entities inside it to be cut off at the edges (instead of being drawn over the surrounding user interface):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zvlctk9ajr379k1m4rv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zvlctk9ajr379k1m4rv.png" alt="game objects staying snugly inside the play area"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Device-Independent Pixels and Density
&lt;/h3&gt;

&lt;p&gt;Something else to be aware of when doing any kind of rendering tasks in Compose for Desktop is to &lt;strong&gt;keep the units of measurement in the back of your mind&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Wherever I worked with coordinates, I decided to work in &lt;a href="https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp" rel="noopener noreferrer"&gt;&lt;strong&gt;device-independent pixels&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;mouse pointer position&lt;/strong&gt; is stored as a &lt;code&gt;DpOffset&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Game width&lt;/strong&gt; and &lt;strong&gt;height&lt;/strong&gt; are stored as &lt;code&gt;Dp&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Game objects&lt;/strong&gt; are placed on the play surface using their &lt;code&gt;.dp&lt;/code&gt; coordinates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helps the game work consistently across high-density displays and low-density displays alike. However, it also &lt;strong&gt;requires some operations to be performed in the context of &lt;code&gt;Density&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, the &lt;code&gt;pointerMoveFilter&lt;/code&gt; returns an &lt;code&gt;Offset&lt;/code&gt; in pixels – and &lt;strong&gt;they are not device-independent&lt;/strong&gt;!. To work around this, we obtain the local screen density in our composition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;density&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDensity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then use &lt;code&gt;with(density)&lt;/code&gt; to access the &lt;code&gt;toDp()&lt;/code&gt; extension functions to the &lt;code&gt;Offset&lt;/code&gt; into a &lt;code&gt;DpOffset&lt;/code&gt;, allowing us to store our &lt;code&gt;targetLocation&lt;/code&gt; in this device-independent pixel format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pointerMoveFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onMove&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;density&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;targetLocation&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DpOffset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDp&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDp&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For storing the play area's width and height, we do a very similar thing, just without wrapping it in a &lt;code&gt;DpOffset&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onSizeChanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;density&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Game of Geometry and Linear Algebra &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Underneath the visualization, the "Asteroids" game builds on just a few basic blocks to implement its mechanics – it is really a game of vectors and linear algebra:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;position&lt;/strong&gt;, &lt;strong&gt;movement&lt;/strong&gt;, and &lt;strong&gt;acceleration&lt;/strong&gt; of the ship can be described by &lt;em&gt;position, movement, and acceleration vectors&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;orientation&lt;/strong&gt; of the ship is the &lt;em&gt;angle&lt;/em&gt; of the &lt;em&gt;vector&lt;/em&gt; between the ship and the cursor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circle-circle collisions&lt;/strong&gt; can be tested based on &lt;em&gt;distance vectors&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of reinventing the &lt;del&gt;wheel&lt;/del&gt; vector, I decided to use &lt;code&gt;openrndr-math&lt;/code&gt;, which includes an implementation of the &lt;code&gt;Vector2&lt;/code&gt; class including all common operations, like scalar multiplication, addition, subtraction, the dot product, and more. (Ever since listening to the &lt;a href="https://talkingkotlin.com/openrndr-with-edwin-jakobs/" rel="noopener noreferrer"&gt;Talking Kotlin&lt;/a&gt; episode, I've been meaning to explore &lt;a href="https://openrndr.org/" rel="noopener noreferrer"&gt;OPENRNDR&lt;/a&gt; in detail, but that will have to happen in a separate project.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://api.openrndr.org/openrndr-math/openrndr-math/org.openrndr.math/-vector2/index.html" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4t373i87ll0hb6e6zsvn.png" alt="OPENRNDR Vector2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As somebody who happens to be a bit rusty with their linear algebra skills, I extended the functionality of the class a bit. For example, I defined the following extension function to allow me to access the angle a &lt;code&gt;Vector2&lt;/code&gt; in degrees between 0-360:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;rawAngle&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atan2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rawAngle&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="nc"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thankfully, I did not have to spend too much time on figuring out the call to &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.math/atan2.html" rel="noopener noreferrer"&gt;&lt;code&gt;atan2&lt;/code&gt;&lt;/a&gt;, because I previously watched one of &lt;a href="http://twitter.com/intelligibabble" rel="noopener noreferrer"&gt;Leland Richardson&lt;/a&gt;'s &lt;a href="https://www.youtube.com/watch?v=fwn7olJOc70" rel="noopener noreferrer"&gt;live streams&lt;/a&gt; where he also uses this function to calculate some angles.&lt;/p&gt;

&lt;p&gt;Extensions like this one help me express ideas in ways I understand them myself – and hopefully still will a few months down the road.&lt;/p&gt;

&lt;p&gt;I also made use of properties with &lt;a href="https://kotlinlang.org/docs/properties.html#getters-and-setters" rel="noopener noreferrer"&gt;backing fields&lt;/a&gt; to make it possible to access a &lt;code&gt;GameObject&lt;/code&gt;'s movement vector in different representations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As a combination of &lt;strong&gt;length&lt;/strong&gt; (speed) and &lt;strong&gt;angle&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;As a vector with &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the context of a &lt;code&gt;GameObject&lt;/code&gt;, that can look like the following, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;speed&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;angle&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;position&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;movementVector&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UNIT_X&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;
        &lt;span class="n"&gt;angle&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we're using this functionality outside of the &lt;code&gt;GameObject&lt;/code&gt; class a lot, we could also consider defining additional &lt;code&gt;length&lt;/code&gt; / &lt;code&gt;angle&lt;/code&gt; getters and setters as extension properties on the &lt;code&gt;Vector2&lt;/code&gt; class, directly.&lt;/p&gt;

&lt;p&gt;For our simulation, we still need to do a bit more – we haven't yet addressed the problem of how to update location and speed based on the elapsed real time. Let's talk about the approach for that next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frame-Independent Movement With Delta Timing &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When building game logic, we need to keep one essential point in mind: &lt;strong&gt;Not all frames are created equal!&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On a 60 Hz display, each frame is visible for 16ms.&lt;/li&gt;
&lt;li&gt;On a 120 Hz display, that number drops to 8.3ms.&lt;/li&gt;
&lt;li&gt;On a 240 Hz display, each frame only shows for 4.2ms.&lt;/li&gt;
&lt;li&gt;On a system under load, or while running in a non-focused window, the application frame rate may be lower than 60 Hz.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means that &lt;strong&gt;we can't use "frames" as a measurement of time&lt;/strong&gt;: If we define the speed of our spaceship in relation to the frame rate, it would move four times faster on a 240 Hz display than on a 60 Hz display.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo8s3j8b4v0zx8b3eozn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo8s3j8b4v0zx8b3eozn.png" alt="frame-based"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We need to &lt;strong&gt;decouple the game logic&lt;/strong&gt; (and its rudimentary "physics simulation") &lt;strong&gt;from the frame rate&lt;/strong&gt; at which our application runs. Even &lt;a href="https://youtu.be/qpC43CdvjyA?t=25" rel="noopener noreferrer"&gt;AAA games&lt;/a&gt; don't get this right all the time – but for our projects, we can do better!&lt;/p&gt;

&lt;p&gt;A straightforward approach for this decoupling is to use &lt;a href="https://en.wikipedia.org/wiki/Delta_timing" rel="noopener noreferrer"&gt;&lt;strong&gt;delta timing&lt;/strong&gt;&lt;/a&gt;: We calculate the new game state based on the &lt;em&gt;time difference&lt;/em&gt; (the &lt;em&gt;delta&lt;/em&gt;) since the last time we updated the game. &lt;br&gt;
This usually means we &lt;em&gt;multiply&lt;/em&gt; the result of our calculations with the time delta, &lt;em&gt;scaling&lt;/em&gt; the result based on the elapsed time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3dnr7776bas1ly70yjvr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3dnr7776bas1ly70yjvr.png" alt="time-based"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Compose for Desktop, we use &lt;code&gt;withFrameMillis&lt;/code&gt; and &lt;code&gt;withFrameNanos&lt;/code&gt;. Both of them provide a timestamp, so we just need to keep track of the previous timestamp to calculate the &lt;code&gt;delta&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;prevTime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0L&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;delta&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;prevTime&lt;/span&gt;
    &lt;span class="c1"&gt;// . . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, a &lt;code&gt;GameObject&lt;/code&gt; has an &lt;code&gt;update&lt;/code&gt; function that takes a &lt;code&gt;realDelta: Float&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;velocity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;movementVector&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;realDelta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As demonstrated in the code above, I use it to scale the velocity of game objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;This concludes our tour of building a small game with Compose for Desktop! To see how all the pieces fit together, read the source code (~300 lines of code) on &lt;a href="https://github.com/SebastianAigner/asteroids-compose-for-desktop" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Building Asteroids on Compose for Desktop was great fun! I am always surprised by the iteration speed that &lt;a href="https://www.jetbrains.com/lp/compose/" rel="noopener noreferrer"&gt;Compose for Desktop&lt;/a&gt; provides: &lt;strong&gt;Getting from a first rectangle to a full game in just one long evening.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of course, implementing a retro game like Asteroids on modern hardware comes with the luxury of not having to think too hard about performance optimizations, allocations, entity-component systems, or more. When building something more ambitious, these points likely need addressing, and you might find yourself using a few additional libraries besides a &lt;code&gt;Vector2&lt;/code&gt; implementation.&lt;/p&gt;

&lt;p&gt;For the next &lt;a href="https://en.wikipedia.org/wiki/Super_Hexagon" rel="noopener noreferrer"&gt;Super Hexagon&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Roguelike" rel="noopener noreferrer"&gt;pixel roguelike&lt;/a&gt;, or other 2D game, however, you can definitely &lt;strong&gt;give Compose a shot&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once again, you can find all 300 lines of source code for this project on &lt;a href="https://github.com/SebastianAigner/asteroids-compose-for-desktop" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're looking for additional inspiration, take a look at some other &lt;strong&gt;folks building games with Compose&lt;/strong&gt;!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vivek Sharma built &lt;a href="https://twitter.com/V9vek/status/1350156513625534464" rel="noopener noreferrer"&gt;everybody's favorite dinosaur game&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;vitaviva built &lt;a href="https://twitter.com/vitaviva2/status/1379876842560122886" rel="noopener noreferrer"&gt;Tetris with Compose&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;John O'Reilly made a &lt;a href="https://github.com/joreilly/chip-8" rel="noopener noreferrer"&gt;Compose for Desktop CHIP-8 frontend&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;theapache64 pushes the limits of Compose's builtin components to implement &lt;a href="https://twitter.com/theapache64/status/1379735815023030279" rel="noopener noreferrer"&gt;Switch, Check, and Radio Snake&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gamedev</category>
      <category>kotlin</category>
      <category>jetpackcompose</category>
      <category>android</category>
    </item>
    <item>
      <title>How I built an "Asteroids" game using Jetpack Compose for Desktop</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Thu, 06 May 2021 13:03:23 +0000</pubDate>
      <link>https://dev.to/kotlin/how-i-built-an-asteroids-game-using-jetpack-compose-for-desktop-309l</link>
      <guid>https://dev.to/kotlin/how-i-built-an-asteroids-game-using-jetpack-compose-for-desktop-309l</guid>
      <description>&lt;p&gt;A while ago, I tweeted about a small game I had created on top of &lt;a href="https://www.jetbrains.com/lp/compose/"&gt;&lt;strong&gt;Jetpack Compose for Desktop&lt;/strong&gt;&lt;/a&gt;: A small clone of the &lt;strong&gt;classic arcade game&lt;/strong&gt; &lt;a href="https://en.wikipedia.org/wiki/Asteroids_(video_game)"&gt;&lt;strong&gt;Asteroids&lt;/strong&gt;&lt;/a&gt;, in which you control a space ship with your mouse, and navigate the vastness of space, avoiding and breaking asteroids in the process.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1382668779377762305-462" src="https://platform.twitter.com/embed/Tweet.html?id=1382668779377762305"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1382668779377762305-462');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1382668779377762305&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Today, it's time to take a look under the hood and understand how I built a basic version of this game, and how &lt;strong&gt;Compose for Desktop helped me achieve it in just one evening&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;We will take a look at parts and structures in the code that I find the most interesting. To see how it all fits together, I suggest exploring the &lt;a href="https://github.com/SebastianAigner/asteroids-compose-for-desktop"&gt;&lt;strong&gt;whole code on GitHub&lt;/strong&gt;&lt;/a&gt;. The whole implementation is &lt;strong&gt;only 300 lines of code&lt;/strong&gt;, which I hope makes studying and understanding it easy.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Game
&lt;/h3&gt;

&lt;p&gt;If you're not caught up on your 80s arcade trivia, &lt;a href="https://en.wikipedia.org/wiki/Asteroids_(video_game)"&gt;Asteroids&lt;/a&gt; was a  popular arcade game where you try to steer your space ship through space, avoiding and destroying asteroids with your ship.&lt;/p&gt;

&lt;p&gt;Because of the limitations of the hardware at the time, the game is quite simplistic in appearance: a triangular spaceship moves across a plain background and avoids simple displays of asteroids on a 2D surface.&lt;/p&gt;

&lt;p&gt;What makes this a challenge is the &lt;em&gt;interia&lt;/em&gt;: Just like a real space ship, your spaceship moves along its course in a straight line at constant speed, and you need to make corrective maneuvers by turning your ship and directing your thrust.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Asteroids has achieved cult status in the arcade game scene.&lt;/strong&gt; Because of that, I wanted to see what it would take to recreate this experience using Jetpack Compose for Desktop!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Building Blocks
&lt;/h3&gt;

&lt;p&gt;I have roughly divided the project into a few building blocks that make up the project, and that we will talk about. Namely, those are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Game Loop&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Game State Management&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rendering to the Screen&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;strong&gt;&lt;a href="https://dev.to/kotlin/tips-tricks-for-building-a-game-using-jetpack-compose-for-desktop-266o"&gt;second part&lt;/a&gt;&lt;/strong&gt; of this series on building a game with Compose for Desktop, we will also look at additional &lt;strong&gt;rendering details&lt;/strong&gt;, the &lt;strong&gt;geometry and linear algebra&lt;/strong&gt; behind the game, and &lt;strong&gt;frame-independent movement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's dive right in!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Game Loop &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;At the center of most games stands the &lt;strong&gt;game loop&lt;/strong&gt;. It acts as the &lt;strong&gt;entry point&lt;/strong&gt; that calls the game logic code. This is a fundamental difference between implementing typical declarative user interfaces and building games:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Declarative UI&lt;/strong&gt; is usually mostly static, and reacts to user actions (clicking, dragging) or other events (new data, computation progress...)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Games&lt;/strong&gt; run their logic many times per second, simulating the game world and its entities one frame at a time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not to say that these two approaches are incompatible! All we need to run a main "game loop" is to get our &lt;strong&gt;function to execute&lt;/strong&gt; once per frame. In Jetpack Compose, we have the &lt;code&gt;withFrame&lt;/code&gt; family of functions (&lt;code&gt;withFrameMillis&lt;/code&gt;, &lt;code&gt;withFrameNanos&lt;/code&gt;), which can help us achieve exactly that.&lt;/p&gt;

&lt;p&gt;Let's assume we already have a &lt;code&gt;game&lt;/code&gt; object – we will talk about state management shortly. We can then create a &lt;code&gt;LaunchedEffect&lt;/code&gt; which asks Jetpack Compose for Desktop to &lt;strong&gt;call our &lt;code&gt;update&lt;/code&gt; function whenever a new frame is rendered&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;withFrameNanos&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;withFrameNanos&lt;/code&gt; is a suspending method. Its exact implementation is described in the &lt;a href="https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#withframemillis"&gt;documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;withFrameNanos&lt;/code&gt; suspends until a new frame is requested, immediately invokes &lt;code&gt;onFrame&lt;/code&gt; with the frame time in nanoseconds in the calling context of frame dispatch, then resumes with the result from &lt;code&gt;onFrame&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The frame time, which it provides us with, will also come in handy, as we will see in the &lt;a href="https://dev.to/kotlin/tips-tricks-for-building-a-game-using-jetpack-compose-for-desktop-266o"&gt;second part&lt;/a&gt; of this blog post series, when we talk about &lt;em&gt;frame-independent movement&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Game State Management &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Jetpack Compose is excellent at managing state&lt;/strong&gt;, and when building a game like Asteroids, we can use the same mechanisms to keep track of the data attached to game objects or the current play session, to name just two examples.&lt;/p&gt;

&lt;p&gt;As suggested in the previous section, my Asteroids game has a &lt;code&gt;Game&lt;/code&gt; class, an instance of which is wrapped in a &lt;code&gt;remember&lt;/code&gt; call in the main composition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It acts as a container for all game-related data. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Game object information (in a &lt;code&gt;mutableStateListOf&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The current game phase (&lt;code&gt;RUNNING&lt;/code&gt; / &lt;code&gt;STOPPED&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The size of the playing field (based on window dimensions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside the &lt;code&gt;Game&lt;/code&gt; object, we treat the state data as mutable, and make any state changes as we see fit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Objects
&lt;/h3&gt;

&lt;p&gt;Individual game objects once again group the state belonging to an individual game entity: a spaceship, an asteroid, or a bullet, and provide methods to modify their state, spawn new game objects, or check their relation to other game objects.&lt;/p&gt;

&lt;p&gt;In my implementation of Asteroids, all game objects share a lot of behavior, from the way they move through the environment to how they check their collision – we'll talk about the geometry and linear algebra that goes into that a bit later.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;GameObject&lt;/code&gt; class provides implementations for these shared behaviors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ZERO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;speed&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;angle&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;position&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;movementVector&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;realDelta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;velocity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;movementVector&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;realDelta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;
        &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;overlapsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;distanceTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, the &lt;code&gt;ShipData&lt;/code&gt; class inherits &lt;code&gt;speed&lt;/code&gt;, &lt;code&gt;angle&lt;/code&gt;, &lt;code&gt;position&lt;/code&gt; and its &lt;code&gt;update&lt;/code&gt; method from &lt;code&gt;GameObject&lt;/code&gt;, but defines its own size, angle, and a function to fire a bullet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShipData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;40.0&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;visualAngle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ship&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;
        &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gameObjects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BulletData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ship&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ship&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visualAngle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ship&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;ShipData&lt;/code&gt; (or even a &lt;code&gt;GameObject&lt;/code&gt; in general) does not include any logic on how to render this item to the display – &lt;strong&gt;with Jetpack Compose, keeping state and presentation separated is quite easy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because a lot of behavior is shared between all types of entities in the game, our main game loop can treat them as the supertype &lt;code&gt;GameObject&lt;/code&gt; for the most part, and only specific interactions between certain types of objects, like bullet-asteroid or asteroid-player collisions, need to be handled specifically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering to the Screen &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I found that in Jetpack Compose, &lt;strong&gt;separating game data from the visual representation comes quite naturally&lt;/strong&gt;. Game objects like a ship, an asteroid, or a bullet are all represented in two parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A class holding the state associated with the game object (in terms of "Compose state" – via &lt;code&gt;mutableStateOf&lt;/code&gt; and friends) – We briefly talked about this in the previous section.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;@Composable&lt;/code&gt;, defining the rendering based on the game object's data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To illustrate the latter, here's the minimal visual representation of the &lt;code&gt;Asteroid&lt;/code&gt; composable. It receives &lt;code&gt;asteroidData&lt;/code&gt;, which is the container for all information regarding the state of this particular game object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;Asteroid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asteroidData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AsteroidData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;asteroidSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asteroidData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;
    &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asteroidData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xOffset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asteroidData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yOffset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asteroidSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asteroidData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFloat&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CircleShape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;153&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code snippet is enough to &lt;strong&gt;describe the whole visual representation&lt;/strong&gt; of an asteroid.&lt;/p&gt;

&lt;p&gt;We start with a &lt;a href="https://developer.android.com/jetpack/compose/layout"&gt;&lt;code&gt;Box&lt;/code&gt;&lt;/a&gt; – one of Compose's most basic layout primitives, which allows us to have entities overlap (which is useful since we manually take care of placing the individual entities). We then use Jetpack Compose's &lt;a href="https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier"&gt;&lt;code&gt;Modifier&lt;/code&gt;s&lt;/a&gt; to specify the position of the asteroid in the form of an &lt;code&gt;offset&lt;/code&gt;, its size, rotation angle, shape (by clipping a &lt;code&gt;CircleShape&lt;/code&gt;), and background color.&lt;/p&gt;

&lt;p&gt;Note that Compose offers quite &lt;strong&gt;high-level APIs even for these basic shapes&lt;/strong&gt; – for example, we can use &lt;code&gt;.rotate&lt;/code&gt; directly, without having to manually do geometry work to figure out how to get our entities facing the right way.&lt;/p&gt;

&lt;p&gt;To keep this snippet as concise as possible, I've also introduced some extension functions on &lt;code&gt;GameObject&lt;/code&gt; that make it possible to reuse the logic of computing the offset of a game object based on its position and size, called &lt;code&gt;xOffset&lt;/code&gt; and &lt;code&gt;yOffset&lt;/code&gt;, which I've snuck into the previous code snippet already. Their implementation is relatively straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xOffset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Dp&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yOffset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Dp&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A slightly more complicated composable would be the &lt;code&gt;Ship&lt;/code&gt; component, which combines the shapes of a triangle and circle to create a minimalistic spaceship:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;Ship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shipData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ShipData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;shipSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shipData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;
    &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shipData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xOffset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shipData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yOffset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shipSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shipData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visualAngle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFloat&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CircleShape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Black&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxSize&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;onDraw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;drawPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;White&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shipSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPx&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="nf"&gt;moveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Top-left corner...&lt;/span&gt;
                    &lt;span class="nf"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;2f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ...to right-center...&lt;/span&gt;
                    &lt;span class="nf"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ... to bottom-left corner.&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Box&lt;/code&gt; defining the ship is quite similar to the one we saw for an &lt;code&gt;Asteroid&lt;/code&gt;, but we additionally add a &lt;code&gt;Canvas&lt;/code&gt; to draw some additional shapes on top of our spaceship – in this case, a triangle path. In typical Compose fashion, we just add this &lt;code&gt;Canvas&lt;/code&gt; in the lambda block following our &lt;code&gt;Box&lt;/code&gt;, meaning the &lt;code&gt;Canvas&lt;/code&gt; will inhert the coordinate system of its parent, including its offset and rotation.&lt;/p&gt;

&lt;p&gt;These composables are then just rendered to a &lt;em&gt;play surface&lt;/em&gt; – nothing more than a &lt;code&gt;Box&lt;/code&gt; with a locked aspect ratio of &lt;code&gt;1.0f&lt;/code&gt; (to keep it quadratic). Of course, applying some artistic talent to these visual representations of the game is also possible, but we're keeping it minimal for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continued in Part 2
&lt;/h2&gt;

&lt;p&gt;There's still a bit more work to do until we can call our game done. In part 2 of this blog post series, we will look at additional rendering details, the geometry and linear algebra behind the game's simple physics simulation, as well as frame-independent movement. &lt;strong&gt;&lt;a href="https://dev.to/kotlin/tips-tricks-for-building-a-game-using-jetpack-compose-for-desktop-266o"&gt;Read on and find out!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>kotlin</category>
      <category>jetpackcompose</category>
      <category>android</category>
    </item>
    <item>
      <title>Why Learn Kotlin?</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Wed, 28 Apr 2021 18:00:55 +0000</pubDate>
      <link>https://dev.to/kotlin/why-learn-kotlin-358n</link>
      <guid>https://dev.to/kotlin/why-learn-kotlin-358n</guid>
      <description>&lt;p&gt;&lt;em&gt;Ksenia Shneyveys, Kotlin Marketing Manager for Education, shares insights on how and why to get started with the Kotlin programming language&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We would love to hear about your own motivations for learning Kotlin by &lt;a href="https://blog.jetbrains.com/kotlin/2021/04/why-learn-kotlin/"&gt;leaving your story on our official blog!&lt;/a&gt; If you share your story with us, you will also have the chance to win an “&lt;a href="https://leanpub.com/AtomicKotlin"&gt;Atomic Kotlin&lt;/a&gt;” ebook!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kotlin has always been and continues to be a modern language in the industry, addressing the real needs of real developers. It is increasingly being adopted in many trending fields, including &lt;a href="https://kotlinlang.org/lp/mobile/"&gt;mobile&lt;/a&gt;, &lt;a href="https://kotlinlang.org/docs/js-overview.html"&gt;web&lt;/a&gt;, &lt;a href="https://kotlinlang.org/lp/server-side/"&gt;server-side&lt;/a&gt; and cloud development, &lt;a href="https://kotlinlang.org/docs/data-science-overview.html"&gt;data science&lt;/a&gt;, and &lt;a href="https://kotlinlang.org/education/"&gt;education&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This all gives a strong indication that there is already significant demand for Kotlin developers and there will continue to be in the future.&lt;/p&gt;

&lt;p&gt;So where can you start learning this skill? “&lt;a href="https://leanpub.com/AtomicKotlin"&gt;Atomic Kotlin&lt;/a&gt;”!&lt;/p&gt;

&lt;p&gt;This book is suited for Kotlin learners of all levels, and it is available in print and as an ebook. It breaks Kotlin programming language concepts into atoms, and provides hands-on exercises inside IntelliJ IDEA.&lt;/p&gt;

&lt;p&gt;To celebrate the recent release of “Atomic Kotlin”, we asked our &lt;a href="https://twitter.com/kotlin"&gt;Twitter&lt;/a&gt; community to share their motivation for learning Kotlin. You all did not disappoint! There were a lot of great responses from the community, and we saw a couple of patterns emerging. In this post, we are going to share with you some of the answers people gave about why Kotlin is a great language to learn.&lt;/p&gt;

&lt;p&gt;&lt;a title="Buy your copy" href="https://leanpub.com/AtomicKotlin"&gt;Buy your copy&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Modern Language
&lt;/h2&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;&lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt; &lt;br&gt;I love Kotlin because it is clean, logical, safe, fast, modern, flexible, intuitive, versatile, and sits on the shoulder of the Java giant.&lt;/p&gt;— Jan Meww (@JanMeww) &lt;a href="https://twitter.com/JanMeww/status/1367028610335399937?ref_src=twsrc%5Etfw"&gt;March 3, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;&lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt; I want to learn more about Kotlin because of the modern syntax and some new ideas (e.g. coroutines) it brings to the current Java Web Development. Have tried it for some weeks and has been a bliss!!!&lt;/p&gt;— Fabio Salas (&lt;a class="mentioned-user" href="https://dev.to/fabiosalasm"&gt;@fabiosalasm&lt;/a&gt;) &lt;a href="https://twitter.com/fabiosalasm/status/1366842511306723333?ref_src=twsrc%5Etfw"&gt;March 2, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kotlin is a modern programming language that combines all the best bits of imperative, object-oriented, and functional programming. It is general-purpose and multi-paradigm, and conciseness and safety are some of the language's key features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easy to Learn
&lt;/h2&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;Why I want to learn Kotlin? well..You don’t come across a language that often which is as elegant and easy to learn like Kotlin. To put icing on the cake it can coexist with your Java ecosystems as well ..what more can you ask &lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt;&lt;/p&gt;— Nirmal (@thooskoo) &lt;a href="https://twitter.com/thooskoo/status/1371518867281956866?ref_src=twsrc%5Etfw"&gt;March 15, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://kotlinlang.org/docs/basic-syntax.html"&gt;Kotlin’s syntax&lt;/a&gt; is simple to grasp for beginners, while at the same time, the language offers sophisticated powerful features for experienced programmers.&lt;/p&gt;

&lt;p&gt;Kotlin can build on the learners’ previous programming experience. It is simple to grasp for those with a Java or Python background. Kotlin’s syntax is also easy to learn for iOS developers because it is based on the same modern concepts they are already familiar with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Great Materials
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;I have gone through the sample of Atomic kotlin book, solved exercises from github repo. It's truely awesome &amp;amp; I want to learn the whole content. I want to use only one language to most of my application development to ship it to different platform - Kotlin &lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt;&lt;/p&gt;— Kalaiselvan (@kalaiselvan369) &lt;a href="https://twitter.com/kalaiselvan369/status/1367862374200315906?ref_src=twsrc%5Etfw"&gt;March 5, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is a lot of up-to-date material available to help you learn Kotlin. One of our favorite resources for learning Kotlin from scratch is “&lt;a href="https://leanpub.com/AtomicKotlin"&gt;Atomic Kotlin&lt;/a&gt;”. Readers can see their progress while solving the tasks that are checked automatically within &lt;a href="https://www.jetbrains.com/edu-products/download/#section=idea"&gt;IntelliJ IDEA&lt;/a&gt;. There are hints and solutions to help them out if they get stuck. All the examples in "Atomic Kotlin" are available in this &lt;a href="https://github.com/BruceEckel/AtomicKotlinExamples"&gt;GitHub repository&lt;/a&gt;. You can compile, run, and test the examples which are automatically extracted directly from the book.&lt;/p&gt;

&lt;p&gt;&lt;a title="Buy your copy" href="https://leanpub.com/AtomicKotlin"&gt;Buy your copy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can learn what the authors of "Atomic Kotlin", &lt;a href="https://www.mindviewllc.com/"&gt;Bruce Eckel&lt;/a&gt; and Svetlana Isakova, think about learning the language in this episode of the JetBrains Connect series. In it, they discuss the question of why to learn Kotlin, with host Paul Everitt:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/0V-qp-qpjzU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiplatform
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt; &lt;br&gt;&lt;br&gt;Want to learn Kotlin since I want to be a multi platform developer &amp;amp; focus more on building the product in different platforms rather than on learning different languages. I believe Kotlin would give me feathers to fly between platforms &amp;amp; reach my true potential.&lt;/p&gt;— jplus (@jplus62611121) &lt;a href="https://twitter.com/jplus62611121/status/1371451253377486859?ref_src=twsrc%5Etfw"&gt;March 15, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;I'm a Ruby developer but want to learn Kotlin as my next language because it have all signs of a modern and concise programming language and it reads well too, which is important. I can build various things with it starting from API to fully-fledged Android app. Fun &lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt;&lt;/p&gt;— Костромицкий Денис (&lt;a class="mentioned-user" href="https://dev.to/mojobiri"&gt;@mojobiri&lt;/a&gt;) &lt;a href="https://twitter.com/mojobiri/status/1367405922864271362?ref_src=twsrc%5Etfw"&gt;March 4, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a language that supports multiplatform targets, you can run Kotlin on virtually any device these days, be it a PC or a Mac, and also as native code. This means you can build mobile, web frontend, and backend applications with Kotlin as well.&lt;/p&gt;

&lt;p&gt;In addition to being the official language for Android development, Kotlin is a proven technology for building cross-platform mobile applications. It eliminates all the disadvantages of other leading approaches and lets you create mobile apps with native performance and UIs while sharing the business logic completely. Visit the &lt;a href="https://kotlinlang.org/lp/mobile/"&gt;Kotlin Multiplatform Mobile portal&lt;/a&gt; to learn more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Progression from Java
&lt;/h2&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;I really like the JVM, and I already know some Kotlin, but I would definitely like to learn more and get better at it, and learn more about the JVM too. Kotlin combines a lot of features from languages that I really like. &lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt;&lt;/p&gt;— Moiré (@Moire9_) &lt;a href="https://twitter.com/Moire9_/status/1367544838569160714?ref_src=twsrc%5Etfw"&gt;March 4, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;Because I’m finishing my studies which were heavily focused on Java and I just started a job in which I use Kotlin every day. No reason not to exceed the expectations! &lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt;&lt;/p&gt;— Bartosz Rogowski (@rogowskibart) &lt;a href="https://twitter.com/rogowskibart/status/1370813212086706177?ref_src=twsrc%5Etfw"&gt;March 13, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;&lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt;&lt;br&gt;Because I want to write Kotlin, not Java with Kotlin syntax. Currently coding together with Spring and I love it.&lt;/p&gt;— MeSmash (@MeSmash3) &lt;a href="https://twitter.com/MeSmash3/status/1366829146777792525?ref_src=twsrc%5Etfw"&gt;March 2, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kotlin’s interoperability allows it to be introduced seamlessly anywhere you’re already using Java. Kotlin fixes some of the issues Java suffers from and has some features that are absent from Java.&lt;/p&gt;

&lt;h2&gt;
  
  
  Career prospects
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;As a self-learner, I started with a couple of Java courses in December. Since then I've been pursuing Kotlin and have been engaged in learning the Kotlin ecosystem to land my first dev job! Having material to build on my foundation of the language will be impactful! &lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt;&lt;/p&gt;— Bryan (@Lidberg_B) &lt;a href="https://twitter.com/Lidberg_B/status/1370850705251180552?ref_src=twsrc%5Etfw"&gt;March 13, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;Knowing, cOncise, pragmaTic, Legible, sImple, perfomiNg... &lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt;&lt;br&gt;My learning with these features will make my career grow and my university dream came true through this language.&lt;/p&gt;— Miguel Paulista (@mikePaulista_13) &lt;a href="https://twitter.com/mikePaulista_13/status/1369329285656350723?ref_src=twsrc%5Etfw"&gt;March 9, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://kotlinlang.org/#usage-highlights"&gt;Many great companies&lt;/a&gt; already use Kotlin to build their products, and Kotlin skills are increasingly in demand as more and more businesses are adopting the language. Indeed, the number of Kotlin job postings has skyrocketed by 1400% since 2017 (Source: &lt;a href="https://insights.dice.com/2019/06/24/kotlin-how-why-tech-professionals-use-it/"&gt;Dice&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Driven
&lt;/h2&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;&lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt; Kotlin is a community driven language and they give great importance for the feedback from devs. I feel good to be invested in such Lang and I believe it has a great future!&lt;/p&gt;—     (@GopalAkshintala) &lt;a href="https://twitter.com/GopalAkshintala/status/1366948847881101315?ref_src=twsrc%5Etfw"&gt;March 3, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;blockquote data-conversation="none"&gt;
&lt;p&gt;Because I'm believing in Kotlin Team and their works(books, features, libraries and everything made by Kotlin)&lt;a href="https://twitter.com/hashtag/atomickotlin?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#atomickotlin&lt;/a&gt;&lt;/p&gt;— Hamza GATTAL (@hmzgtl05) &lt;a href="https://twitter.com/hmzgtl05/status/1370832650429202434?ref_src=twsrc%5Etfw"&gt;March 13, 2021&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since its very beginning in 2011, Kotlin has been developed as an open-source language.&lt;/p&gt;

&lt;p&gt;Kotlin evolves with the help of our &lt;a href="https://kotlinlang.org/community/"&gt;diverse community&lt;/a&gt;, which includes almost &lt;a href="https://kotlinlang.org/user-groups/user-group-list.html"&gt;200 Kotlin User Groups&lt;/a&gt;, 37K+ &lt;a href="https://surveys.jetbrains.com/s3/kotlin-slack-sign-up"&gt;Kotlinlang Slack&lt;/a&gt; users, and countless other members spread across our &lt;a href="https://discuss.kotlinlang.org/"&gt;forum&lt;/a&gt;, our &lt;a href="https://www.reddit.com/r/Kotlin/"&gt;sub-Reddit&lt;/a&gt;, &lt;a href="https://www.youtube.com/channel/UCP7uiEZIqci43m22KDl0sNw"&gt;YouTube&lt;/a&gt;, &lt;a href="https://twitter.com/kotlin"&gt;Twitter&lt;/a&gt;, and many other platforms. Over 450 contributors are working on Kotlin, including 90 JetBrains developers.&lt;/p&gt;

&lt;p&gt;Your feedback provides the basis for &lt;a href="https://kotlinlang.org/docs/roadmap.html"&gt;our roadmap&lt;/a&gt;. Thank you for your continued support!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did you Learn Kotlin?
&lt;/h2&gt;

&lt;p&gt;If you haven’t already taken up Kotlin, we hope that this post has left you feeling inspired to do so. We would love to hear about your own motivations for learning Kotlin by &lt;a href="https://blog.jetbrains.com/kotlin/2021/04/why-learn-kotlin/"&gt;leaving your story on our official blog!&lt;/a&gt; If you share your story with us, you will also have the chance to win an “&lt;a href="https://leanpub.com/AtomicKotlin"&gt;Atomic Kotlin&lt;/a&gt;” ebook!&lt;/p&gt;

&lt;p&gt;We’ll select 5 winners from the commenters on &lt;a href="https://blog.jetbrains.com/kotlin/2021/04/why-learn-kotlin/"&gt;blog.jetbrains.com&lt;/a&gt; on May 12.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>programming</category>
      <category>beginners</category>
      <category>100daysofcode</category>
    </item>
    <item>
      <title>Diving into Kotlin collections</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Mon, 29 Mar 2021 18:00:41 +0000</pubDate>
      <link>https://dev.to/kotlin/diving-into-kotlin-collections-587o</link>
      <guid>https://dev.to/kotlin/diving-into-kotlin-collections-587o</guid>
      <description>&lt;p&gt;This blog post accompanies a video from our &lt;strong&gt;YouTube series&lt;/strong&gt; which you can find on our &lt;a href="https://kotl.in/video" rel="noopener noreferrer"&gt;Kotlin YouTube channel&lt;/a&gt;, or &lt;strong&gt;watch here&lt;/strong&gt; directly!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/F8jj7e-_jFA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kotlinlang.org/docs/collections-overview.html" rel="noopener noreferrer"&gt;Kotlin Collections&lt;/a&gt;! You’ve heard of them, you’ve used them – so it makes sense to learn even more about them! Kotlin's standard library provides &lt;strong&gt;awesome tools to manage groups of items&lt;/strong&gt;, and we’re going to take a closer look!&lt;/p&gt;

&lt;p&gt;Let's see &lt;strong&gt;what types of collections&lt;/strong&gt; the Kotlin standard library offers, and explore a &lt;strong&gt;common subset of operations&lt;/strong&gt; that’s available for all of the collections you get in the standard library. Let’s get started.&lt;/p&gt;

&lt;p&gt;In the Kotlin standard library, we have three big types of collections: &lt;strong&gt;Lists&lt;/strong&gt;, &lt;strong&gt;Sets&lt;/strong&gt;, and &lt;strong&gt;Maps&lt;/strong&gt;. Just like many other parts of the standard library, these &lt;strong&gt;collections are available anywhere you can write Kotlin&lt;/strong&gt;: on the JVM, but also in Kotlin/Native, Kotlin/JS, and common Kotlin code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lists
&lt;/h2&gt;

&lt;p&gt;Let’s start with the &lt;strong&gt;most popular candidate&lt;/strong&gt; of a collection in Kotlin: a &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/" rel="noopener noreferrer"&gt;&lt;code&gt;List&lt;/code&gt;&lt;/a&gt;. To rehearse:&lt;/p&gt;

&lt;p&gt;A list is a collection of &lt;strong&gt;ordered elements&lt;/strong&gt;. That means that you can access the elements of a list using &lt;strong&gt;indices&lt;/strong&gt; – so you can say “give me the element at position two”. There’s also &lt;strong&gt;no constraints on duplicate elements&lt;/strong&gt; in our list. We can just put in whatever elements we’d like. So, very few constraints on content, and maximum versatility in how we access the elements!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;aList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Apple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Banana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Cherry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Apple"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;aList&lt;/span&gt; &lt;span class="c1"&gt;// [Apple, Banana, Cherry, Apple]&lt;/span&gt;

&lt;span class="n"&gt;aList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// Banana&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sets
&lt;/h2&gt;

&lt;p&gt;Next up, we have the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-set/" rel="noopener noreferrer"&gt;&lt;code&gt;Set&lt;/code&gt;&lt;/a&gt;! Sets are groups of objects where we don’t care about the order of elements. Instead, we want to make sure that our collection &lt;strong&gt;never contains any duplicates&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s the key property of a set: all of its &lt;strong&gt;contents are unique&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That makes sets a bit more of a specialized data structure, but there’s a good chance you want to use them in everyday scenarios anyway.&lt;/p&gt;

&lt;p&gt;What are &lt;strong&gt;typical things&lt;/strong&gt; you might want to store in a set? Tags, for example. Or, maybe you’re building a social network, and you want to store the IDs of all the friends that a certain user has. In both cases, you don't want to have duplicates in these collections, and probably don't care about the order.&lt;/p&gt;

&lt;p&gt;A set can help you &lt;strong&gt;enforce these constraints&lt;/strong&gt; without having to really think about it, and &lt;strong&gt;without manual duplication checks&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;emotions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Happy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Curious"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Joyful"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Happy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// even if we try to add duplicates...&lt;/span&gt;
    &lt;span class="s"&gt;"Joyful"&lt;/span&gt; &lt;span class="c1"&gt;// ...to our set...&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;emotions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ...the elements in our set stay unique!&lt;/span&gt;
&lt;span class="c1"&gt;// [Happy, Curious, Joyful]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sets are actually also a &lt;strong&gt;common mathematical abstraction&lt;/strong&gt;. Typical mathematical concepts, like &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/union.html" rel="noopener noreferrer"&gt;unions&lt;/a&gt;, &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/intersect.html" rel="noopener noreferrer"&gt;intersections&lt;/a&gt;, or the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/subtract.html" rel="noopener noreferrer"&gt;set difference&lt;/a&gt; also translate neatly into Kotlin code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maps
&lt;/h2&gt;

&lt;p&gt;Last, but certainly not least, we have &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/" rel="noopener noreferrer"&gt;&lt;code&gt;Map&lt;/code&gt;&lt;/a&gt;. A map is a &lt;strong&gt;set of key-value pairs&lt;/strong&gt;, where &lt;strong&gt;each key is unique&lt;/strong&gt;. It’s also sometimes called a “dictionary” for that reason. You encounter maps whenever you’re &lt;strong&gt;associating data&lt;/strong&gt; – storing a persons name and their favorite pizza topping, or associating a license plate with vehicle information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;peopleToPizzaToppings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="s"&gt;"Ken"&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="s"&gt;"Pineapple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"Lou"&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="s"&gt;"Peperoni"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;"Ash"&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="s"&gt;"Ketchup"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;peopleToPizzaToppings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// {Ken=Pineapple, Lou=Peperoni, Ash=Ketchup}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Ash"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;// Ketchup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key-value pairs are everywhere, and just like in many other languages, maps are the go-to way to manage them in Kotlin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collections can be mutable
&lt;/h2&gt;

&lt;p&gt;By default, these collections in Kotlin are &lt;strong&gt;read-only&lt;/strong&gt;. This is in the spirit of &lt;strong&gt;immutability&lt;/strong&gt; which accompanies typical functional paradigms – instead of changing the contents of a collection, you create a new collection with the changes applied, which you can then &lt;strong&gt;safely pass around&lt;/strong&gt; in your application, ensuring that the &lt;strong&gt;original collection stays unchanged&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3avccfflc4ugw7l0xykt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3avccfflc4ugw7l0xykt.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But we also have &lt;strong&gt;mutable flavors&lt;/strong&gt; of all of the collections in Kotlin: we have &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/" rel="noopener noreferrer"&gt;&lt;code&gt;MutableList&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-set/" rel="noopener noreferrer"&gt;&lt;code&gt;MutableSet&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/" rel="noopener noreferrer"&gt;&lt;code&gt;MutableMap&lt;/code&gt;&lt;/a&gt;. Those are modifiable, meaning you can &lt;strong&gt;comfortably add and remove elements&lt;/strong&gt;. With data where you’re inherently expecting change, you’d probably use these mutable variants.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collections are iterable
&lt;/h2&gt;

&lt;p&gt;Kotlin collections being &lt;em&gt;iterable&lt;/em&gt; means that the standard library provides a &lt;strong&gt;common, standardized set of typical operations for collections&lt;/strong&gt;, for example, to retrieve their size, check if they contain a certain item, and more.&lt;/p&gt;

&lt;p&gt;Lists and sets directly implement the Collection interface, which in turn implements the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-iterable/" rel="noopener noreferrer"&gt;&lt;code&gt;Iterable&lt;/code&gt;&lt;/a&gt; interface. Maps have an &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/iterator.html" rel="noopener noreferrer"&gt;&lt;code&gt;iterator()&lt;/code&gt;&lt;/a&gt; operator function, and provide iterable properties, like their set of keys, their list of values, as well as the entries of the map, so key-value pairs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7j7a868lyz9dowlwnrn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7j7a868lyz9dowlwnrn.png" alt="image"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Let’s learn about some &lt;strong&gt;shared functionality of iterables&lt;/strong&gt;. The following examples are going to use a list, but really, we can just assume that we’re just working with an &lt;code&gt;Iterable&lt;/code&gt; here – the concrete implementation does not matter. Also, all the functions discussed &lt;strong&gt;leave the original collection unchanged&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looping over collections
&lt;/h2&gt;

&lt;p&gt;A core function of an &lt;code&gt;Iterable&lt;/code&gt;, as its name suggests, is that it provides a mechanism to &lt;strong&gt;access the elements&lt;/strong&gt; that our collection contains, one after the other – to iterate it.&lt;/p&gt;

&lt;p&gt;The easiest way to go through all the elements in a collection is the basic Kotlin &lt;a href="https://kotlinlang.org/docs/control-flow.html#for-loops" rel="noopener noreferrer"&gt;&lt;code&gt;for&lt;/code&gt;&lt;/a&gt; loop. When we use the &lt;code&gt;for&lt;/code&gt; loop with an &lt;code&gt;Iterable&lt;/code&gt;, the &lt;code&gt;in&lt;/code&gt; operator cleverly understands that we want to &lt;strong&gt;go over the iterator&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fruits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Apple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Banana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Cherry"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruit&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Apple&lt;/span&gt;
&lt;span class="c1"&gt;// Banana&lt;/span&gt;
&lt;span class="c1"&gt;// Cherry&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a &lt;strong&gt;more functional style&lt;/strong&gt;, we can also write this same snippet using the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/for-each.html" rel="noopener noreferrer"&gt;&lt;code&gt;forEach&lt;/code&gt;&lt;/a&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fruit&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Apple&lt;/span&gt;
&lt;span class="c1"&gt;// Banana&lt;/span&gt;
&lt;span class="c1"&gt;// Cherry&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;forEach&lt;/code&gt; takes every element from our collection, and &lt;strong&gt;calls a function&lt;/strong&gt; (which we provide) with the element as its argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transforming collections: map
&lt;/h2&gt;

&lt;p&gt;Let's continue with a classic when it comes to &lt;strong&gt;transforming collections&lt;/strong&gt;: the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map.html" rel="noopener noreferrer"&gt;&lt;code&gt;map&lt;/code&gt;&lt;/a&gt; function! (Don’t be confused! The &lt;code&gt;map&lt;/code&gt; function has nothing to do with the &lt;code&gt;Map&lt;/code&gt; collection type. You can treat them as two completely different things.)&lt;/p&gt;

&lt;p&gt;Just like the &lt;code&gt;forEach&lt;/code&gt; function, the &lt;code&gt;map&lt;/code&gt; function is of &lt;a href="https://kotlinlang.org/docs/lambdas.html" rel="noopener noreferrer"&gt;higher order&lt;/a&gt;. So, it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Takes each element&lt;/strong&gt; from our collection, &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;applies a function&lt;/strong&gt; to it, and&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;creates another collection&lt;/strong&gt;, containing the return values of those function applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result of the map function doesn’t have to be the same type as the one of our input collection, either.&lt;/p&gt;

&lt;p&gt;This makes the &lt;code&gt;map&lt;/code&gt; function &lt;strong&gt;very versatile&lt;/strong&gt; – whether you want to parse a collection of strings into a collection of integers, or resolve a list of user names to a list of full user profiles –– if you’re &lt;strong&gt;transforming one collection into another&lt;/strong&gt;, it’s probably a good &lt;strong&gt;first instinct&lt;/strong&gt; to think &lt;code&gt;map&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fruits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Apple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Banana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Cherry"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;stiurf&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, you might have a transformation inside your &lt;code&gt;map&lt;/code&gt; function where you &lt;strong&gt;can’t generate valid results&lt;/strong&gt; for all input elements. In this case, we can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map-not-null.html" rel="noopener noreferrer"&gt;&lt;code&gt;mapNotNull&lt;/code&gt;&lt;/a&gt; function, and our resulting collection will only contain those function results that &lt;strong&gt;evaluated to an actual value&lt;/strong&gt;. This also ensures that type of our resulting variable is &lt;strong&gt;non-nullable&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;strs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"three"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"V"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mapNotNull&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toIntOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 4] &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we need to &lt;strong&gt;keep track of the index&lt;/strong&gt; of the element which we’re currently transforming, we can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map-indexed.html" rel="noopener noreferrer"&gt;&lt;code&gt;mapIndexed&lt;/code&gt;&lt;/a&gt; function. It’s quite similar in how it works, but in this case, we get &lt;strong&gt;two parameters in our transformation function&lt;/strong&gt;: the &lt;em&gt;index&lt;/em&gt; and the &lt;em&gt;value&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;rank&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Gold"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Silver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Bronze"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ranking&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mapIndexed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;"$m ($idx)"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ranking&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="na"&gt;[Gold (0), Silver (1), Bronze (2)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Filtering collections: filter and partition
&lt;/h2&gt;

&lt;p&gt;If we have a collection, but we’re only interested in &lt;strong&gt;elements that fulfil a certain condition&lt;/strong&gt;, the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter.html" rel="noopener noreferrer"&gt;&lt;code&gt;filter&lt;/code&gt;&lt;/a&gt; function comes to the rescue!&lt;/p&gt;

&lt;p&gt;Just like the previous examples, &lt;code&gt;filter&lt;/code&gt; accepts &lt;strong&gt;another function as its parameter&lt;/strong&gt;. This time, instead of defining a transformation, we’re defining what you can call a &lt;strong&gt;predicate&lt;/strong&gt; here.&lt;/p&gt;

&lt;p&gt;A predicate is a function that takes a collection element and &lt;strong&gt;returns a boolean value&lt;/strong&gt;: &lt;code&gt;true&lt;/code&gt; means that the given element matches the predicate, &lt;code&gt;false&lt;/code&gt; means the opposite. So this predicate acts as the “&lt;strong&gt;doorman&lt;/strong&gt;” – if the value is &lt;code&gt;true&lt;/code&gt;, the collection item is let through to the result collection, otherwise, it is discarded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cyborg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;people&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Agatha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Amber"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Cyborg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Rob"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;discoVisitors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;discoVisitors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [Agatha, Amber, Rob]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re testing a &lt;strong&gt;negative condition&lt;/strong&gt;, you can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-not.html" rel="noopener noreferrer"&gt;&lt;code&gt;filterNot&lt;/code&gt;&lt;/a&gt; function instead, which behaves identically, but &lt;strong&gt;inverts the condition&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;students&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filterNot&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [Joe]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that both &lt;code&gt;filter&lt;/code&gt; and &lt;code&gt;filterNot&lt;/code&gt; &lt;strong&gt;discard elements&lt;/strong&gt; where the condition doesn’t match. But maybe we don’t want to discard the “other half” of elements, and instead we want to put those into a separate list. This is where the &lt;code&gt;partition&lt;/code&gt; function comes into play.&lt;/p&gt;

&lt;p&gt;By using &lt;code&gt;partition&lt;/code&gt;, we &lt;strong&gt;combine the powers&lt;/strong&gt; of &lt;code&gt;filter&lt;/code&gt; and &lt;code&gt;filterNot&lt;/code&gt;. It returns a &lt;strong&gt;pair of lists&lt;/strong&gt;, where the first list contains all the elements for which the predicate holds true, and the second contains all the elements that fail the test. So, in our doorman analogy, instead of sending people who fail the check away, we just send them to a different place. (Using parentheses, we can &lt;strong&gt;destructure&lt;/strong&gt; this pair of lists directly into two independent variables.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;adults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;partition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [Agatha, Amber, Rob]&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [Joe]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re bringing a &lt;strong&gt;collection of nullable items&lt;/strong&gt; to the party, you can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-not-null.html" rel="noopener noreferrer"&gt;&lt;code&gt;filterNotNull&lt;/code&gt;&lt;/a&gt; function which, as you may have guessed, &lt;strong&gt;automatically discards any elements that are &lt;code&gt;null&lt;/code&gt;&lt;/strong&gt;, and gives you a new collection with an adjusted, non-nullable type accordingly.&lt;/p&gt;

&lt;p&gt;Speaking of adjusting types – if your collection contains multiple elements from a type hierarchy, but you’re only interested in &lt;strong&gt;elements of a specific type&lt;/strong&gt;, you can use &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-is-instance.html" rel="noopener noreferrer"&gt;&lt;code&gt;filterIsInstance&lt;/code&gt;&lt;/a&gt;, and specify the desired type as a generic parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;people&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Agatha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Amber"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Cyborg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Rob"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;actualPeople&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filterNotNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actualPeople&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [Joe, Agatha, Amber, Rob]&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;cyborgs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filterIsInstance&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Cyborg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cyborgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [Rob]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Retrieve collection parts: take and drop
&lt;/h2&gt;

&lt;p&gt;Filtering allowed us to apply a predicate function, and create a new collection containing items that match. But what about the even simpler cases? Sometimes, we just want to &lt;strong&gt;grab a few elements&lt;/strong&gt; from our collection.&lt;/p&gt;

&lt;p&gt;For that, we have the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/take.html" rel="noopener noreferrer"&gt;&lt;code&gt;take&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/drop.html" rel="noopener noreferrer"&gt;&lt;code&gt;drop&lt;/code&gt;&lt;/a&gt; functions. You might already be able to guess what they do. &lt;code&gt;take&lt;/code&gt; gives you a &lt;strong&gt;collection of the first n elements&lt;/strong&gt; from your original collection. So &lt;code&gt;take(2)&lt;/code&gt; is going to give you the first two elements. On the opposite hand, &lt;code&gt;drop(3)&lt;/code&gt; is going to &lt;strong&gt;leave out the first three elements&lt;/strong&gt; of your original collection, and only gives you everything that follows after those three elements. And you don’t have to be afraid to “overdrop” either – dropping more elements from a collection than it contains just gives you an empty list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;objects&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🌱"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🚀"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"💡"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"🐧"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⚙️"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;seedlingAndRocket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seedlingAndRocket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🌱, 🚀]&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;penguinAndGear&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;penguinAndGear&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// [🐧, ⚙️]&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;nothing&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nothing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// []&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// remember, the original collection is not modified!&lt;/span&gt;
&lt;span class="c1"&gt;// [🌱, 🚀, 💡, 🐧, ⚙️]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One huge benefit of the functions we’ve seen so far is their &lt;strong&gt;composability&lt;/strong&gt;: Because mapping, filtering, taking, dropping, and all their friends return a new collection, it’s easy to just take that result, and &lt;strong&gt;immediately use it as an argument for the next collection function&lt;/strong&gt;, turning collection into collection into collection.&lt;/p&gt;

&lt;p&gt;However, we should keep in mind that chaining a number of these functions together means we generate a bunch of &lt;strong&gt;intermediate collections&lt;/strong&gt;. Now, this isn’t going to set your computer on fire immediately, but it is still something to be aware of, especially when you work with very large collections. For this case, Kotlin has a few aces up its sleeve as well, called &lt;a href="https://kotlinlang.org/docs/sequences.html" rel="noopener noreferrer"&gt;sequences&lt;/a&gt;, but we will dive into those at a later point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aggregating collections: sums, averages, minimums, maximums, and counting
&lt;/h2&gt;

&lt;p&gt;Once we’re done transforming our data, we might want to get a &lt;strong&gt;single result value&lt;/strong&gt; out of it. If we have a collection of &lt;strong&gt;numerical values&lt;/strong&gt; like integers or doubles, we get some nice functions called &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/average.html" rel="noopener noreferrer"&gt;&lt;code&gt;average&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sum.html" rel="noopener noreferrer"&gt;&lt;code&gt;sum&lt;/code&gt;&lt;/a&gt; out of the box, which help us calculate those values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;randomNumbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;randomNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;average&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;// 4.09090909090909091&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;randomNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;// 45&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In some situations (...or, we might say, &lt;em&gt;sum&lt;/em&gt; situations...), we have a collection of more &lt;strong&gt;complex objects&lt;/strong&gt;, and want to still &lt;strong&gt;add them up&lt;/strong&gt; somehow, based on their properties. Of course, we could first use the &lt;code&gt;map&lt;/code&gt; function to obtain a collection containing only numbers – but by using the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sum-of.html" rel="noopener noreferrer"&gt;&lt;code&gt;sumOf&lt;/code&gt;&lt;/a&gt; function, we can do all of this in a single function call: we can pass a function that acts as a &lt;strong&gt;selector&lt;/strong&gt; (so a function that gives us whatever number we want to associate with the element) and &lt;code&gt;sumOf&lt;/code&gt; will use the &lt;strong&gt;result of that selector function&lt;/strong&gt; to &lt;strong&gt;add up&lt;/strong&gt; all our elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;randomNames&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Dallas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Kane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Ripley"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Lambert"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;cumulativeLength&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;randomNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sumOf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cumulativeLength&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 23&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we’re only interested in the &lt;strong&gt;greatest or smallest value&lt;/strong&gt; contained in our collection of numbers, we can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/max-or-null.html" rel="noopener noreferrer"&gt;&lt;code&gt;maxOrNull&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/min-or-null.html" rel="noopener noreferrer"&gt;&lt;code&gt;minOrNull&lt;/code&gt;&lt;/a&gt; functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;randomNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;minOrNull&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;// 9&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;randomNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;maxOrNull&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And just like &lt;code&gt;sumBy&lt;/code&gt;, we have the sibling functions &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/max-of.html" rel="noopener noreferrer"&gt;&lt;code&gt;maxOf&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/min-of.html" rel="noopener noreferrer"&gt;&lt;code&gt;minOf&lt;/code&gt;&lt;/a&gt;, where we once again pass a &lt;strong&gt;selector function&lt;/strong&gt;, which is going to be used to &lt;strong&gt;determine the maximum or minimum&lt;/strong&gt; of a collection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;longestName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;randomNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;maxOf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;longestName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 7&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;shortestName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;randomNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;minOf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shortestName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we just care about the &lt;strong&gt;number of elements&lt;/strong&gt; contained in our collection, we can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/count.html" rel="noopener noreferrer"&gt;&lt;code&gt;count&lt;/code&gt;&lt;/a&gt; function – either without any parameters, to just get the number of all elements, or using a &lt;strong&gt;predicate&lt;/strong&gt;. So that’s like filtering the collection first, and then counting the elements. But again, all wrapped into one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val digits = randomNumbers.count()

println(digits)
// 11

val bigDigits = randomNumbers.count { it &amp;gt; 5 }

println(bigDigits)
// 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s also the powerful &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/join-to-string.html" rel="noopener noreferrer"&gt;&lt;code&gt;joinToString&lt;/code&gt;&lt;/a&gt; function, which allows us to &lt;strong&gt;turn all elements of our collection into a string&lt;/strong&gt;, complete with a metric ton of customization options like separators, prefixes and postfixes, limits or a placeholder if you have more elements than what your specified limit allows. And even &lt;code&gt;joinToString&lt;/code&gt; accepts a &lt;strong&gt;transformation function&lt;/strong&gt;, once again, so you don’t need to do some kind of separate mapping beforehand, it’s all built in. Truly powerful stuff to create a string from a collection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;str&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;randomNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinToString&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;separator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pi://"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"[$it]"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// pi://[3]-[1]-[4]-[1]-[5]-...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to refresh what kind of magic we can do with Kotlin strings, watch the Kotlin Standard Library episode that takes us into the depth of strings!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/n4WBip822A8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  More collection goodness, coming soon!
&lt;/h2&gt;

&lt;p&gt;That concludes our overview of Kotlin collections!&lt;/p&gt;

&lt;p&gt;Next, we’re going to step up our game even more, and will take a look at some advanced collection functionality. Some of the functions we’ve seen today actually have some additional variants to them, which are worth an introduction. There’s also the whole world of modifying collections. Plus, each type of collection we’ve seen, Lists, Sets, and Maps, all have their own specialized functionality as well, We’re in for a whole bunch more Kotlin collection content!&lt;/p&gt;

&lt;p&gt;Make sure you don’t miss it! To get reminded when new content is released, follow us here on &lt;a href="https://dev.to/kotlin"&gt;dev.to/kotlin&lt;/a&gt;, and make sure to follow me on Twitter &lt;a href="https://twitter.com/sebi_io" rel="noopener noreferrer"&gt;@sebi_io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, make sure to find the subscribe button and notification bell on our &lt;a href="https://kotl.in/video" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;If you don’t want to wait until that episode comes out, there’s only one solution! It’s time to go and explore some more Kotlin!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>programming</category>
      <category>android</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Natural language processing with Kotlin: Part-of-speech tagging with Hidden Markov Model</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Mon, 22 Mar 2021 12:52:12 +0000</pubDate>
      <link>https://dev.to/kotlin/natural-language-processing-with-kotlin-part-of-speech-tagging-with-hidden-markov-model-1gan</link>
      <guid>https://dev.to/kotlin/natural-language-processing-with-kotlin-part-of-speech-tagging-with-hidden-markov-model-1gan</guid>
      <description>&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="https://twitter.com/mariakhalusova" rel="noopener noreferrer"&gt;Maria Khalusova&lt;/a&gt; for agreeing to cross-posting her article here. For more articles like this, check out &lt;a href="https://www.mariakhalusova.com/" rel="noopener noreferrer"&gt;her blog.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In NLP, part-of-speech tagging is a process in which you mark words in a text (aka corpus) as corresponding parts of speech (e.g., noun, verb, etc.). This task is fundamental to natural language processing and has multiple applications, for instance, &lt;a href="https://en.wikipedia.org/wiki/Named-entity_recognition" rel="noopener noreferrer"&gt;Named Entity Recognition&lt;/a&gt;, or &lt;a href="https://en.wikipedia.org/wiki/Word-sense_disambiguation" rel="noopener noreferrer"&gt;Word Sense Disambiguation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The task may seem straightforward at first glance, but it becomes difficult when you realize that some words can be ambiguous, and their part-of-speech tag depends on the context. For example, take the word "sleep". In a sentence "I plan to sleep until lunchtime tomorrow.", this word is a verb. However, in the sentence "How much sleep does one really need?", it is a noun.&lt;/p&gt;

&lt;p&gt;How do you go about this problem? We can group the most commonly used approaches into two categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Probabilistic methods: In these methods, you assign a tag based on the probability of it occurring in a given sentence. One of such approaches uses Hidden Markov Models, and that's what this post covers.&lt;/li&gt;
&lt;li&gt;Deep Learning methods: Getting state-of-the-art results requires complex recurrent neural networks, such as Meta-BiLSTM Model described in &lt;a href="https://arxiv.org/abs/1805.08237" rel="noopener noreferrer"&gt;this paper&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, I've chosen to cover Hidden Markov Models for a couple of reasons. First, these models are amazingly versatile, and part-of-speech tagging is only one of their applications. Others include signal processing, speech recognition, handwriting recognition, musical score following, and much more... Perhaps, once you know how Hidden Markov Model works, you'll find your own application for it! Second, the algorithm used for retrieving tag predictions, the Viterbi algorithm, didn't click with me at first, and I had to spend some time building the intuition for it. So if my explanation helps you understand it, I would have saved you some time :) Finally, if you really would rather read about Deep Learning, don't worry, I'll be digging into some version of LSTM in one of the latter articles.&lt;/p&gt;

&lt;p&gt;So here's what you'll learn from this post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is Markov Model?&lt;/li&gt;
&lt;li&gt;What is Hidden Markov Model?&lt;/li&gt;
&lt;li&gt;How to prepare data&lt;/li&gt;
&lt;li&gt;Calculating Transition and Emission Matrices&lt;/li&gt;
&lt;li&gt;Motivation for Viterbi algorithm&lt;/li&gt;
&lt;li&gt;Viterbi initialization&lt;/li&gt;
&lt;li&gt;Viterbi forward pass&lt;/li&gt;
&lt;li&gt;Viterbi backward pass&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start with what Markov Chains are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Markov Model
&lt;/h2&gt;

&lt;p&gt;A Markov chain is a mathematical system that transitions from one state to another according to certain probabilistic rules. An important property of this system (also called "Markov property") is that the probability of transitioning to any particular state depends &lt;strong&gt;solely&lt;/strong&gt; on the current state.&lt;/p&gt;

&lt;p&gt;Let's illustrate this with a toy example. Suppose, every day we observe the weather, and it is always one of the following: sunny, rainy, or cloudy (and for simplicity no other weather conditions exist). These are called states. Day after day we note it down, and as such, we create a sequence of observations. We can describe this situation with a Markov model:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv9688s3iigfrqynqf4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv9688s3iigfrqynqf4i.png" alt="Weather states"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each day we are in one of the states - it's either sunny, rainy, or cloudy, and every day we transition into another state. If it's sunny two days in a row, it means that we transition from state "sunny" to itself, but the transition still happens. After collecting the weather observations for some time, we can calculate the probabilities of transitioning from one state to another (including into the same state). These are the numbers that you see on the transitions. For example, if it's sunny today, the probability that it will be cloudy tomorrow is 0.4. And, according to the Markov property the weather (aka state) tomorrow depends only on the weather (aka state) today.&lt;/p&gt;

&lt;p&gt;We can write all the transition probabilities from this Markov model as a matrix A:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;s1 (Sunny)&lt;/th&gt;
&lt;th&gt;s2 (Cloudy)&lt;/th&gt;
&lt;th&gt;s3 (Rainy)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;s1 (Sunny)&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;0.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;s2 (Cloudy)&lt;/td&gt;
&lt;td&gt;0.2&lt;/td&gt;
&lt;td&gt;0.2&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;s3 (Rainy)&lt;/td&gt;
&lt;td&gt;0.7&lt;/td&gt;
&lt;td&gt;0.15&lt;/td&gt;
&lt;td&gt;0.15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In matrix A, a number in a cell 

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;aija_ij&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 represents the probability of transitioning from state i to state j. Because a transition to some state has to happen (even if it is to itself), the numbers in each row must add up to 1.&lt;/p&gt;

&lt;p&gt;Once we have modeled the weather like this, we can answer all sorts of questions. For example, if it has been sunny today, what is the probability that it will be sunny tomorrow? The answer to this you can simply look up in the matrix - 0.5 (50% chance). We can also answer more complex questions, like, if we have started with a sunny day, what is the probability to have the following sequence of days - [Sunny, Sunny, Rainy, Cloudy, Sunny]?&lt;br&gt;
This is where we would use the Markov property.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P([s1,s1,s3,s2,s1]∣Model)=P(s1)∗P(s1∣s1)∗P(s3∣s1)∗P(s2∣s3)∗P(s1∣s2)
P([s1, s1, s3, s2, s1] | Model ) = P(s1) * P(s1 | s1)*P(s3 | s1) * P(s2 | s3) * P(s1 | s2)
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;([&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;]&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;3∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;2∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;All these numbers except for the first one we have in the transition matrix A, and the first one we know from the problem&lt;br&gt;
statement (P(s1) = 1 because we started with a sunny day):&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P([s1,s1,s3,s2,s1]∣Model)=1∗a11∗a13∗a32∗a21=1∗0.5∗0.1∗0.15∗0.2=0.0015
P([s1, s1, s3, s2, s1] | Model ) = 1 * a_11 * a_13 * a_32 * a_21  = 1 * 0.5 * 0.1 * 0.15 * 0.2 = 0.0015
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;([&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;]&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.5&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.15&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.2&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.0015&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Now, this was a toy example to give you an intuition for the Markov model, its states, and transition probabilities. However, things are a little more complicated with Part of Speech tagging, and we will need a Hidden Markov Model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hidden Markov Model
&lt;/h2&gt;

&lt;p&gt;In the previous examples, the states were types of weather, and we could directly observe them. The name "Hidden Markov Model" implies that we cannot directly observe the states themselves, but instead we can observe something else. Back to the Part of Speech tagging task, our hidden states will be parts of speech. So what is instead observed? The data that the algorithm will "see" is text - a sequence of words. These words are the actual observations from the data. How can we now model this situation? To simplify things let's pretend we only have three hidden states - noun (NN), verb (VB), and other (O).&lt;/p&gt;

&lt;p&gt;Just like in the previous example, we're going to have a matrix with transition probabilities with a minor addition. Here, we're also adding the initial state 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;pipi&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and probabilities to transition from the initial state to any of the hidden states. These probabilities tell us how likely it is that the text begins with one of the given parts of speech.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15o910tx52277ecdgx2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15o910tx52277ecdgx2p.png" alt="POS Transition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition to this, a Hidden Markov Model has Emission probabilities - the probabilities to observe a word given hidden state. For example, given that we are currently in a "verb" state, here are the probabilities to observe each of the actual words in the corpus:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcem661w31p6a1yzud8y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcem661w31p6a1yzud8y.png" alt="Emissions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, you can see that if our model is in the VB (verb) state, there's a 0.15 probability to observe the word "running". The emission probabilities can also be populated in a matrix (we'll call it B), where rows represent each of the possible hidden states (part of speech tags), and columns represent each of the possible observables (words). Thus, the size of this matrix would be &lt;code&gt;number of tags&lt;/code&gt; (states) by &lt;code&gt;number of possible words&lt;/code&gt;. Just like with the transition matrix A, the sum of the numbers in each row has to add up to exactly 1, as in each of the hidden states we have to observe one of the words.&lt;/p&gt;

&lt;p&gt;This is how we can describe the corpus with words and POS tags with a Hidden Markov Model. Given a labeled corpus, "training" a Hidden Markov Model would mean populating the transition and emission matrices. Once that's done, we can use those matrices for calculating predictions using the Viterbi algorithm.&lt;/p&gt;

&lt;p&gt;We'll get to the prediction part later in this article. First, let's see how we can populate these matrices for actual labeled data.&lt;/p&gt;
&lt;h2&gt;
  
  
  Data &amp;amp; Some Preprocessing
&lt;/h2&gt;

&lt;p&gt;The standard dataset that is used for training POS taggers for the English language is the Penn Tree Bank Wall Street Journal dataset. The corpus in it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In        IN
an        DT
Oct.      NNP
19        CD
review    NN
of        IN
''        ''
The       DT
Misanthrope NN
''        ''
at        IN
Chicago   NNP
's        POS
Goodman   NNP
Theatre   NNP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;All words, punctuation marks, and other symbols are marked with corresponding tags, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IN&lt;/strong&gt;: conjunction, subordinating, or preposition. Examples: of, on, before, unless.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DT&lt;/strong&gt;: determiner. Examples: the, a, these.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NNP&lt;/strong&gt;: noun, proper singular. Examples: Germany, God, Alice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CD&lt;/strong&gt;: cardinal number. Examples: five, three, 13%&lt;/li&gt;
&lt;li&gt;...and so on, check the complete description of what all the tags mean &lt;a href="http://relearn.be/2015/training-common-sense/sources/software/pattern-2.6-critical-fork/docs/html/mbsp-tags.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As is the case with any machine learning project, we will use part of that data for training, and reserve the rest for evaluating the model.&lt;/p&gt;

&lt;p&gt;To "train" a Hidden Markov Model and populate the transition and emission matrices, we will need to know what hidden states we have, and what words are in the corpus - the vocabulary.&lt;/p&gt;

&lt;p&gt;To create the vocabulary, we'll take the training chunk of the data, and record all the words that are encountered more than once. At the end of the words we will also add a list of special words: "--n--", "--unk--", "--unk_adj--", "--unk_adv--", "--unk_digit--", "--unk_noun--", "--unk_punct--", "--unk_upper--", "--unk_verb--".&lt;/p&gt;

&lt;p&gt;The first one, "--n--" is the special word for the initial state, the rest ("--unk--", "--unk_adj--", "--unk_adv--", etc.) will replace the unknown words which we will inevitably encounter in both the training and the test corpus.&lt;/p&gt;

&lt;p&gt;Here's one way you can create the vocabulary:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.File&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createVocabulary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trainingDataFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="cm"&gt;/*
    Creates vocabulary from the training data file.
    The vocabulary includes all the words that are encountered more than once.
    This is done so that unknown words would have some representation in the the training data as well.
    The vocabulary is also appended with the list of various types of "unknown", and special "word" indicating
    beginning of the sentence - "--n--"
*/&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;lineList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;trainingDataFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readLines&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;words&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lineList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;getWord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;wordFrequences&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupingBy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;eachCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;vocabFromFile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wordFrequences&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;unknowns&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"--n--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--unk--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--unk_adj--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--unk_adv--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--unk_digit--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--unk_noun--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"--unk_punct--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--unk_upper--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--unk_verb--"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocabFromFile&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;unknowns&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getWord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;word&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"--n--"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\t'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\t'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;trainingData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"src/data/WSJ_02-21.pos"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;vocabulary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createVocabulary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trainingData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"src/data/vocab.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocabulary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we are almost ready to start populating the transition and emission matrices. We only need a few functions that'll help us go over the training data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We'll need some heuristics to replace words that are not in the vocabulary with one of the "--unk_[]--" tokens&lt;/li&gt;
&lt;li&gt;As we will be calculating transition probabilities we'll need to calculate how often each tag comes after another one, which means we'll need to go through the training corpus line by line extracting both the word and the tag.&lt;/li&gt;
&lt;li&gt;Finally, when we'll want to test our model, we'll need to get just the words from the test corpus to generate part of speech predictions for them.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.File&lt;/span&gt;

&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Preprocessor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;//  heuristics for replacing words that are not in the vocabulary with unk-[...]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;nounSuffix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ance"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"dom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ee"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ence"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"er"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hood"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"ion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ism"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ling"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ness"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"or"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"scape"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ship"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ty"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;verbSuffix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ise"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ize"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;adjSuffix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"able"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ese"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ful"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ian"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ible"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ish"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"less"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ous"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;advSuffix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ward"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"wards"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"wise"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;assignUnk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[0-9]"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"--unk_digit--"&lt;/span&gt;
        &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[^A-Za-z0-9 ]"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"--unk_punct--"&lt;/span&gt;
        &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[A-Z]"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"--unk_upper--"&lt;/span&gt;
        &lt;span class="n"&gt;nounSuffix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"--unk_noun--"&lt;/span&gt;
        &lt;span class="n"&gt;verbSuffix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"--unk_verb--"&lt;/span&gt;
        &lt;span class="n"&gt;adjSuffix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"--unk_adj--"&lt;/span&gt;
        &lt;span class="n"&gt;advSuffix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"--unk_adv--"&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"--unk--"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getWordAndTagFromLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\t'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\t'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;word&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\t'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\t'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;containsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;assignUnk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"--n--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--s--"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getTestWordsAndTags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;testDataFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;wordsAndTags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;()&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;lines&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;testDataFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readLines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getWordAndTagFromLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;wordsAndTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"--n--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--s--"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;containsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;wordsAndTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;assignUnk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;wordsAndTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wordsAndTags&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Calculating Transition and Emission Matrices
&lt;/h2&gt;

&lt;p&gt;To populate these matrices, we will start with computing a few helper counts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;transitionCounts&lt;/code&gt;: a &lt;code&gt;mutableMapOf&amp;lt;Pair&amp;lt;String, String&amp;gt;, Int&amp;gt;()&lt;/code&gt; that will contain the number of times a sequence of two tags (tag_i, tag_j) has occurred in that order. We will use that count to later calculate the probability of transitioning from said tag_i to tag_j.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;emissionCounts&lt;/code&gt; a &lt;code&gt;mutableMapOf&amp;lt;Pair&amp;lt;String, String&amp;gt;, Int&amp;gt;()&lt;/code&gt; that will contain the number of times the word_k was came with tag_l. We will use these counts to calculate the emission probability of a word_k given tag_l.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tagCounts&lt;/code&gt;: this map will simply store the number of times each tag occurred.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;calculateCounts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;preprocessor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Preprocessor&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;previousTag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"--s--"&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;trainingCorpus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;preprocessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getWordAndTagFromLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;transitionCounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;previousTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transitionCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;previousTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;emissionCounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emissionCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;tagCounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;previousTag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now that we have all these counts, we can calculate the matrices themselves. For transition matrix, the formula is as follows:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(ti∣ti−1)=C(ti−1,ti)+αC(ti−1)+α∗N
P(t_i | t_{i-1}) = \frac{C(t_{i-1}, t_{i}) + \alpha }{C(t_{i-1}) +\alpha * N}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;α&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;C(ti−1,ti)C(t_{i-1}, t_{i})&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the count of the pair (previous tag, current tag) in the &lt;code&gt;transitionCounts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;C(ti−1)C(t_{i-1})&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the count of the previous tag in the &lt;code&gt;tagCounts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;NN&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the total number of tags.&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;α\alpha&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is a smoothing parameter. Smoothing is a technique that helps us to avoid shooting ourselves in the foot if some of those counts end up being 0. By adding 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;α\alpha&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 in the numerator and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;α∗N\alpha * N&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;α&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 in the denominator, instead of 0, we'll end up with a very small number.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To work with matrices, I'm using &lt;a href="https://github.com/Kotlin/multik" rel="noopener noreferrer"&gt;multik&lt;/a&gt;, a multidimensional array library for Kotlin. It has been publicly released recently, and you can read more about it on the &lt;a href="https://blog.jetbrains.com/kotlin/2021/02/multik-multidimensional-arrays-in-kotlin/" rel="noopener noreferrer"&gt;Kotlin blog&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createTransitionMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;transitionMatrix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;D2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;//      Go through each row and column of the transition matrix&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;//          Define the Pair (prev POS tag, current POS tag)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;//          If the (prev POS tag, current POS tag) exists in the transition counts dictionary, change the count&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transitionCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;//          Get the count of the previous tag (index position i) from tag counts&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;countPrevTag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagCounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

&lt;span class="c1"&gt;//          Apply smoothing to avoid numeric underflow&lt;/span&gt;
        &lt;span class="n"&gt;transitionMatrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;countPrevTag&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Similarly, we calculate the probabilities for the emission matrix.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P(wi∣ti)=C(ti,wordi)+αC(ti)+α∗N
P(w_i | t_i) = \frac{C(t_i, word_i)+ \alpha}{C(t_{i}) +\alpha * N}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;w&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;∣&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;α&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;w&lt;/span&gt;&lt;span class="mord mathnormal"&gt;or&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;C(ti,wordi)C(t_i, word_i)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;w&lt;/span&gt;&lt;span class="mord mathnormal"&gt;or&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
: the number of times 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;wordiword_i&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;w&lt;/span&gt;&lt;span class="mord mathnormal"&gt;or&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 was assosiacted with 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tagitag_i&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 in the training data (stored in &lt;code&gt;emissionCounts&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;C(ti)C(t_i)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
: the count of 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tagitag_i&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 in the &lt;code&gt;tagCounts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;NN&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
: total number of tags.&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;α\alpha&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
: smoothing parameter.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createEmissionProbsMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;emissionProbsMatrix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;D2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_WORDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;reversedVocab&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;associate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_WORDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reversedVocab&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emissionCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;countTag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagCounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
        &lt;span class="n"&gt;emissionProbsMatrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_WORDS&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;countTag&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once we have computed the Transition and Emission matrices we have described our data with a Hidden Markov Model, so we can pat ourselves on the back on this occasion - well deserved!&lt;/p&gt;

&lt;p&gt;Now how can we use these matrices to predict POS tags for a sentence?&lt;/p&gt;
&lt;h2&gt;
  
  
  Viterbi Algorithm: Motivation
&lt;/h2&gt;

&lt;p&gt;First, let's define the problem we are trying to solve here. We have the Hidden Markov Model that contains information about the transition probabilities from each hidden state to another hidden state, and information about the emission probabilities from each hidden state to each word from the vocabulary.&lt;/p&gt;

&lt;p&gt;Now we have a sentence (aka  a sequence of words (= observations)), and we need to find the sequence of tags (hidden states) for this sentence that will yield the highest probability given this sequence of words. In other words, what sequence of tags matches this sentence the best?&lt;/p&gt;

&lt;p&gt;The brute force method of answering this question would mean calculating probabilities for all the possible sequences of tags, and then choosing the one with the highest probability. However, ALL combinations of tags are possible (even if the probability for some is minuscule). So if we had a sentence with only 3 words, and there were only 4 possible tags -  A, B, C, D, we would end up with 3^4 = 81 combinations to search through. In reality, we have 40+ tags, and sentences are typically much longer than 3 words. In general, for a sentence with N words, and T tags the search space of possible state sequences X is 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(NT)O(N^T)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. As you can imagine this quickly becomes way too large to brute force search on.&lt;/p&gt;

&lt;p&gt;Clearly, a smarter alternative is needed, and that's where the Viterbi algorithm can help. The Viterbi algorithm is a Dynamic Programming algorithm that we will use for finding the most likely sequence of hidden states that results in a sequence of observations. Dynamic Programming is a method for solving a complex problem by breaking it down into a collection of simpler subproblems, solving each of those subproblems just once, and storing their solutions using a memory-based data structure. In this case, we'll be taking advantage of knowing that an optimal state sequence X1 . . . Xj . . . XT contains a subsequence X1 . . . Xj, which is also optimal. With that, we'll start building up the optimal sequence step by step, keeping record only of the best probabilities, and the path that got us there, not all the possible paths. This approach allows to bring the complexity down to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(N2∗T)O(N^2 *T)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;As we will need to store intermediate results, we will need two additional matrices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bestProbs&lt;/code&gt;: as we build up the optimal sequence, this is the matrix that will contain intermediate optimal probabilities.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bestPaths&lt;/code&gt;: this matrix will hold the indices of visited states, so that once we finally find the best probability for the full sentence, we could traverse back the &lt;code&gt;bestPaths&lt;/code&gt; to get the actual sequence of states that got us to the highest probability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Viterbi algorithm consists of three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialization&lt;/strong&gt;. At this step we create the auxiliary matrices &lt;code&gt;bestProbs&lt;/code&gt; and &lt;code&gt;bestPaths&lt;/code&gt; and populate the first column of each matrix. Both matrices will have the size of &lt;code&gt;NUMBER_OF_TAGS&lt;/code&gt; rows by &lt;code&gt;sentence.size&lt;/code&gt; columns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forward pass&lt;/strong&gt;: We'll be populating both matrices column by column, at each step finding the best probability and path for the current subsequence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backward pass&lt;/strong&gt;: Finally, we'll use &lt;code&gt;bestPaths&lt;/code&gt; to backtrace the path that yielded the highest probability which we'll get from the last column of &lt;code&gt;bestPaths&lt;/code&gt; corresponding to the last word in the sentence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's dive deeper in each of these steps.&lt;/p&gt;
&lt;h2&gt;
  
  
  Viterbi: Initialization
&lt;/h2&gt;

&lt;p&gt;The first matrix we'll be initializing is the &lt;code&gt;bestProbs&lt;/code&gt; matrix. It has &lt;code&gt;NUMBER_OF_TAGS&lt;/code&gt; rows and as many columns as we have words in a sentence for which we need to predict the tags. At this step we need to populate the first column, and leave the rest to be zeros. The first column represents probabilities to emit the first word given each of the states when we start from the initial state. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bestProbs[1,1] is the probability to start in the hidden state T1 ( which is the same as transition from the initial state to the hidden state T1) and observe the word W1;&lt;/li&gt;
&lt;li&gt;bestProbs[2,1] is the probability to start in the hidden state T2 (aka transition from the initial state to hidden state T2) and observe the word W1;&lt;/li&gt;
&lt;li&gt;and so on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general, &lt;code&gt;bestProbs[i, 1]&lt;/code&gt; can be calculated as product of multiplying the probability to transition from the initial state to hidden state 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;TiT_i&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, and the probability to emit the word W1 given we are in hidden state 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;TiT_i&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. One of these numbers we have in the transition matrix, and the other one we have in the emission matrix. To avoid the arithmetic underflow when dealing with extremely small probabilities, we'll add the logarithm.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;bestPaths&lt;/code&gt; matrix should contain indices of all previously visited states, so for the first column everything is 0. As a note, when creating an empty matrix with multik via &lt;code&gt;mk.empty&amp;lt;Double, D2&amp;gt;(a,b)&lt;/code&gt; it already initializes to all zeros. This means we only need to create an empty matrix of the required size at this step.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;initializeViterbiMatrices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;D2Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="nc"&gt;D2Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/*
    returns two matrices: bestProbs = best probabilities (num of states by num of words in sentence) and
    bestPaths = best paths (num of states by num of words in sentence)
    */&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bestProbs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;D2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bestPaths&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;D2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;startIdx&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"--s--"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;//      populating the first column of the bestProbs to initialize it&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transitionMatrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;bestProbs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NEGATIVE_INFINITY&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;bestProbs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transitionMatrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;startIdx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;emissionProbsMatrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bestProbs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bestPaths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once the matrices have been initialized, we can start populating them column by column in the forward pass. Remember, that each column represents the next word in the sentence. By moving from left to right column by column at each step we increase the subsequence in question by one word.&lt;/p&gt;
&lt;h2&gt;
  
  
  Viterbi: Forward Pass
&lt;/h2&gt;

&lt;p&gt;In the forward pass we start populating the matrices column by column, storing the intermediate best probabilities in &lt;code&gt;bestProbs&lt;/code&gt;, and the path that got us there in &lt;code&gt;bestPaths&lt;/code&gt;. Here's how we calculate what should be in the cell &lt;code&gt;[j,i]&lt;/code&gt; where 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;jj&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;TagjTag_j&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ii&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;wordiword_i&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;w&lt;/span&gt;&lt;span class="mord mathnormal"&gt;or&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;bestProbs[j,i]=max⁡kbestProbsk,i−1∗transitionMatrixk,j∗emissionMatrixj,indexofwordi
bestProbs[j,i] = \max_{k}bestProbs_{k, i-1} * transitionMatrix_{k,j} * emissionMatrix_{j, {index of word i}}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord mathnormal"&gt;es&lt;/span&gt;&lt;span class="mord mathnormal"&gt;tP&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ro&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mopen"&gt;[&lt;/span&gt;&lt;span class="mord mathnormal"&gt;j&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mclose"&gt;]&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop"&gt;max&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord mathnormal"&gt;es&lt;/span&gt;&lt;span class="mord mathnormal"&gt;tP&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ro&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;r&lt;/span&gt;&lt;span class="mord mathnormal"&gt;an&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;r&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∗&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;mi&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ss&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;r&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;j&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;in&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;x&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;f&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;or&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;To simplify, suppose we are calculating bestProbs for the third column. Here's what we do here: We look at the previous (i.e. second) column and find the maximum value in it - this is a cell with the best probability for the previous subsequence. We take that number, and note the tag (k) at which we got the maximum value. That is the tag we will be transitioning from into our current, third column. So now for each tag in the third column we can multiply the best probability value we got for the previous subsequence by the probability to transition from previous best tag into this tag, multiplied by the probability to observe current column's word given this tag.&lt;/p&gt;

&lt;p&gt;At the same time, when calculating bestProbs, we'll be saving the index &lt;code&gt;k&lt;/code&gt; that maximizes the formula into bestPaths so that we not only know the best probability at every step but also keep track of what tag resulted in the best probability.&lt;/p&gt;

&lt;p&gt;This is what this will look like in Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;viterbiForward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bestProbs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;D2Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bestPaths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;D2Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;D2Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="nc"&gt;D2Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;updatedProbs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bestProbs&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;updatedPaths&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bestPaths&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;bestProbabilityToGetToWordIFromTagJ&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NEGATIVE_INFINITY&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;bestPathToWordI&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;temp_prob&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                &lt;span class="n"&gt;updatedProbs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transitionMatrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;emissionProbsMatrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_prob&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bestProbabilityToGetToWordIFromTagJ&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;bestProbabilityToGetToWordIFromTagJ&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp_prob&lt;/span&gt;
                &lt;span class="n"&gt;bestPathToWordI&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;updatedProbs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bestProbabilityToGetToWordIFromTagJ&lt;/span&gt;
        &lt;span class="n"&gt;updatedPaths&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bestPathToWordI&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;updatedProbs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;updatedPaths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we've built the matrices in the forward pass, we can easily get the highest probability - it'll be the maximum value in the last column. However, we are interested not in the probability number itself but in the sequence of tags that yielded this number. In the Backward pass, we'll use the &lt;code&gt;bestPaths&lt;/code&gt; matrix to traceback the tags sequence that have maximizes the probability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Viterbi: Backward Pass
&lt;/h2&gt;

&lt;p&gt;The backward pass is the final step of the Viterbi algorithm. Once we implement it, we'll be able to use this algorithm to generate predictions for the sequence of POS tags matching any sentence.&lt;/p&gt;

&lt;p&gt;In the previous, forward pass, we have populated two matrices - &lt;code&gt;bestProbs&lt;/code&gt; and &lt;code&gt;bestPaths&lt;/code&gt;- that we will now traverse backwards to identify the sequence of tags that is the most likely for the given sequence of words.&lt;/p&gt;

&lt;p&gt;First we need to find the highest value in the last column of the &lt;code&gt;bestProbs&lt;/code&gt;, and get its row index &lt;code&gt;K&lt;/code&gt;. This value is the probability of the most likely sequence of hidden states, matching the given sequence of words. The index K represents the hidden state that we were in when we calculated this probability. That's the POS tag for the last word in the sentence, so let's record K into an array. Now we need to start backtracing the whole sequence of tags, and we will switch to the &lt;code&gt;bestPaths&lt;/code&gt; matrix. In the last column of the &lt;code&gt;bestPaths&lt;/code&gt; we locate the cell with index K. That cell contains the unique ID of the POS tag of the previous word, so we jump there, and continue the same way thus "unrolling" the whole sequence. As we go through the &lt;code&gt;bestPaths&lt;/code&gt; matrix from right to left, in each cell we will find "directions" on where to go next.&lt;/p&gt;

&lt;p&gt;Here's what it could look like if we only had 5 words and 4 tags:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwou81yducgnrlef2lcxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwou81yducgnrlef2lcxx.png" alt="Viberi Backward"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's implement it in Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;viterbiBackward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bestProbs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;D2Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bestPaths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;D2Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;z&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;IntArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;bestProbForLastWord&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NEGATIVE_INFINITY&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;posPredictions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;until&lt;/span&gt; &lt;span class="nc"&gt;NUMBER_OF_TAGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;//          finding the index of the cell with the highest probability in the last column of the bestProbs&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bestProbs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bestProbForLastWord&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;bestProbForLastWord&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bestProbs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;posPredictions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="c1"&gt;//      traversing the bestPaths backwards.&lt;/span&gt;
&lt;span class="c1"&gt;//      each current cell contains the row index of the cell to go to in the next column&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;downTo&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;tagForWordI&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bestPaths&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagForWordI&lt;/span&gt;
        &lt;span class="n"&gt;posPredictions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tagForWordI&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;posPredictions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we can combine all three steps of the Viterbi algorithm into one method that we'll be able to use to predict a sequence of POS tags that best matches any given sentence according to the Hidden Markov Model that we have calculated based on our data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;predictPOSSequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;initialBestProbs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;initialBestPaths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initializeViterbiMatrices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;updatedBestProbs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;updatedBestPaths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;viterbiForward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;initialBestProbs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;initialBestPaths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;viterbiBackward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;updatedBestProbs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;updatedBestPaths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are different ways we could evaluate the performance of this model. For simplicity let's take per-word accuracy - how many words have been assigned correct tag out of all predictions that have been made.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testWords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;testTags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;testTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"The size of testWords list doesn't match the size of the testTags list"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;predictions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predictPOSSequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testWords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;numberOfCorrectPredictions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;predictions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testTags&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;numberOfCorrectPredictions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;predictions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get a good measure of performance, we should always evaluate a model on the data that hasn't been used during the training phase. Let's see how this model does on the test data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficizp93na750bcwodq12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficizp93na750bcwodq12.png" alt="Accuracy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The model we've just build has 95% accuracy. Not too shabby! All this hard work has paid off, and you've reached the end of this lengthy article too. Congratulations!&lt;/p&gt;

&lt;p&gt;PS: If you'd like to toy with the code from this article and build something of your own, feel free to check out this project on &lt;a href="https://github.com/MKhalusova/pos-tagging/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you enjoyed this article, check out &lt;a href="https://www.mariakhalusova.com/" rel="noopener noreferrer"&gt;Maria Khalusova's blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nlp</category>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>Migrating our Kotlin/JS app to the new IR compiler</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Tue, 09 Mar 2021 14:11:05 +0000</pubDate>
      <link>https://dev.to/kotlin/migrating-our-kotlin-js-app-to-the-new-ir-compiler-3o6i</link>
      <guid>https://dev.to/kotlin/migrating-our-kotlin-js-app-to-the-new-ir-compiler-3o6i</guid>
      <description>&lt;p&gt;Together with some colleagues, I maintain a small &lt;strong&gt;full-stack web application&lt;/strong&gt; called CodeQuiz, which we built during a &lt;a href="https://blog.jetbrains.com/blog/2019/11/22/jetbrains-7th-annual-hackathon/" rel="noopener noreferrer"&gt;48-hour hackathon at JetBrains&lt;/a&gt;, and use at &lt;a href="https://www.youtube.com/watch?v=_AM5VbPTKeg" rel="noopener noreferrer"&gt;events&lt;/a&gt; to gamify learning about Kotlin. I recently &lt;strong&gt;migrated its frontend&lt;/strong&gt; which you can see below (and which is using the &lt;a href="https://github.com/JetBrains/kotlin-wrappers/tree/master/kotlin-react" rel="noopener noreferrer"&gt;&lt;code&gt;kotlin-react&lt;/code&gt; wrappers&lt;/a&gt;) to the &lt;strong&gt;new Kotlin/JS IR compiler backend&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bteuocjmnzyj2fi3ovm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bteuocjmnzyj2fi3ovm.gif" alt="CodeQuiz in action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new compiler made a bunch of issues in our code visible, so I wanted to &lt;strong&gt;share my experience&lt;/strong&gt; of migrating a Kotlin/JS app, and provide some &lt;strong&gt;hints&lt;/strong&gt; on where to look when your app behaves unexpectedly after moving to the IR compiler.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the Kotlin/JS IR compiler?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://kotlinlang.org/docs/js-ir-compiler.html" rel="noopener noreferrer"&gt;Kotlin/JS IR compiler&lt;/a&gt; is currently in development (with alpha stability) and on its way to become &lt;strong&gt;the new default&lt;/strong&gt; way of compiling Kotlin to JavaScript. It's a completely re-engineered infrastructure for all things Kotlin/JS. This switch comes with a &lt;strong&gt;number of benefits&lt;/strong&gt; for Kotlin/JS applications!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1362402517976551424-382" src="https://platform.twitter.com/embed/Tweet.html?id=1362402517976551424"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1362402517976551424-382');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1362402517976551424&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Using it allows you to already &lt;strong&gt;test drive&lt;/strong&gt; a bunch of &lt;strong&gt;new features&lt;/strong&gt;, including &lt;a href="https://kotlinlang.org/docs/js-ir-compiler.html#preview-generation-of-typescript-declaration-files-d-ts" rel="noopener noreferrer"&gt;&lt;strong&gt;TypeScript declaration generation&lt;/strong&gt;&lt;/a&gt;, and profit from &lt;strong&gt;new optimizations&lt;/strong&gt; like stronger DCE (and, as a result, &lt;strong&gt;smaller generated artifacts&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;But it also means that you have to embrace its &lt;strong&gt;more strict rules&lt;/strong&gt; regarding &lt;strong&gt;interoperation&lt;/strong&gt; between Kotlin and JavaScript. This might &lt;strong&gt;require some adjustment&lt;/strong&gt; at first, but will help write more predictable code that interoperates between Kotlin and JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why doesn't my code &lt;em&gt;just work&lt;/em&gt;? 😱
&lt;/h2&gt;

&lt;p&gt;Especially with code at the "boundary" between Kotlin and JavaScript, &lt;strong&gt;the legacy compiler was quite lenient&lt;/strong&gt; – for example how it exported all symbols (e.g. a &lt;code&gt;data class&lt;/code&gt;) from Kotlin code to the JavaScript world.&lt;/p&gt;

&lt;p&gt;Unfortunately, this means that it was easy to rely on compiler-specific internal behavior – &lt;strong&gt;some things just &lt;em&gt;happened&lt;/em&gt; to work, even though the compiler gave no guarantees that these things &lt;em&gt;were supposed to work&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When using the IR compiler these &lt;strong&gt;mistakes become visible&lt;/strong&gt; – it enforces &lt;strong&gt;proper, explicit interoperation&lt;/strong&gt; between the world of Kotlin and the world of JavaScript (we call this the &lt;strong&gt;"Closed World" model&lt;/strong&gt;). This stricter and more explicit control will help the compiler &lt;strong&gt;optimize your code&lt;/strong&gt; more aggressively.&lt;/p&gt;

&lt;p&gt;But, due to the nature of JavaScript being a dynamic runtime environment, some of these changes in behavior only appear &lt;strong&gt;during execution time&lt;/strong&gt;. In the case of CodeQuiz, a number of modifications were necessary to get everything working. We'll look at them in detail in the next sections.&lt;/p&gt;

&lt;p&gt;Ultimately, it boiled down to &lt;strong&gt;running and testing&lt;/strong&gt; the application (both in &lt;code&gt;development&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; mode), and keeping an eye on the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Helping Kotlin's DCE via &lt;code&gt;@JsExport&lt;/code&gt; (e.g. React components)&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;external interface&lt;/code&gt; to define React properties (&lt;code&gt;RProps&lt;/code&gt;) and state (&lt;code&gt;RState&lt;/code&gt;) (instead of (&lt;code&gt;data&lt;/code&gt;) &lt;code&gt;class&lt;/code&gt;es) and other areas of interoperation&lt;/li&gt;
&lt;li&gt;Creating plain JavaScript objects for interaction with external components&lt;/li&gt;
&lt;li&gt;Fixing npm dependencies that use &lt;code&gt;export default&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Making sure our Kotlin dependencies support Kotlin/JS IR&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Turning on IR
&lt;/h2&gt;

&lt;p&gt;To use the IR compiler for our project, we make a small change to our &lt;code&gt;build.gradle(.kts)&lt;/code&gt; file. In the &lt;code&gt;kotlin&lt;/code&gt; configuration block, change &lt;code&gt;js&lt;/code&gt; to &lt;code&gt;js(IR)&lt;/code&gt;, and enable the generation of JavaScript artifacts via &lt;code&gt;binaries.executable()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;js&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;binaries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;browser&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;commonWebpackConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cssSupport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;testTask&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;useKarma&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;useChromeHeadless&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;(Alternatively, the compiler type can also be set in the &lt;code&gt;gradle.properties&lt;/code&gt; file, with the key &lt;code&gt;kotlin.js.compiler=ir&lt;/code&gt;, which might be easier if you have a more complex project.)&lt;/p&gt;

&lt;p&gt;We can now cross our fingers and execute the &lt;code&gt;browserDevelopmentRun&lt;/code&gt; Gradle task to &lt;strong&gt;start our application&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's look at some of &lt;strong&gt;the symptoms&lt;/strong&gt; our CodeQuiz app exhibited when first running the application with IR, and let's &lt;strong&gt;correct the related code&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Make JS- and React-related classes external interfaces
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://kotlinlang.org/docs/js-interop.html#declare-static-members-of-a-class" rel="noopener noreferrer"&gt;&lt;code&gt;external&lt;/code&gt; modifier&lt;/a&gt; helps Kotlin understand that a certain &lt;strong&gt;declaration is pure JavaScript&lt;/strong&gt;. This prevents problems like &lt;code&gt;ClassCastException&lt;/code&gt;s that would arise from the &lt;strong&gt;false assumption&lt;/strong&gt; that something is a Kotlin object (like a &lt;code&gt;data class&lt;/code&gt;) – even though in reality, we are dealing with a plain JavaScript object.&lt;/p&gt;

&lt;p&gt;When using &lt;code&gt;react-kotlin&lt;/code&gt;, this can often be observed regarding definitions of &lt;code&gt;RState&lt;/code&gt; and &lt;code&gt;RProps&lt;/code&gt; – with React, &lt;strong&gt;state and properties are pure JavaScript objects&lt;/strong&gt; managed by the framework for us.&lt;/p&gt;
&lt;h3&gt;
  
  
  Turn RState into an external interface
&lt;/h3&gt;

&lt;p&gt;When running my application with IR enabled for the first time, I got the following &lt;code&gt;ClassCastException&lt;/code&gt; in regards to some React components' &lt;code&gt;init&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;codequiz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;19131&lt;/span&gt; &lt;span class="nx"&gt;Uncaught&lt;/span&gt; 
&lt;span class="nx"&gt;ClassCastException&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ClassCastException&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ClassCastException↵    at THROW_CCE (webpack-inter…s/react-dom/cjs/react-dom.development.js:4056:31)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nl"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ClassCastException&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ClassCastException↵    at THROW_CCE (webpack-internal:///./kotlin/codequiz-server.js:19101:11)↵    at App.init (webpack-internal:///./kotlin/codequiz-server.js:101164:69)↵    at RComponent_init_$Init$ (webpack-internal:///./kotlin/codequiz-server.js:31545:11)↵    at new App (webpack-internal:///./kotlin/codequiz-server.js:101148:5)↵    at constructClassInstance (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:12716:18)↵    at updateClassComponent (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:17425:5)↵    at beginWork (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:19073:16)↵    at HTMLUnknownElement.callCallback (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:3945:14)↵    at Object.invokeGuardedCallbackDev (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:3994:16)↵    at invokeGuardedCallback (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:4056:31)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;__proto__&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RuntimeException&lt;/span&gt;
&lt;span class="nx"&gt;THROW_CCE&lt;/span&gt;   &lt;span class="p"&gt;@&lt;/span&gt;   &lt;span class="nx"&gt;codequiz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;19131&lt;/span&gt;
&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;    &lt;span class="p"&gt;@&lt;/span&gt;   &lt;span class="nx"&gt;codequiz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;101224&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The stack trace suggests the &lt;code&gt;init&lt;/code&gt; method of my &lt;code&gt;App&lt;/code&gt; component. Since here, only application state is initialized, it was quite easy to pinpoint the underlying problem.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;offending code&lt;/strong&gt; for the application state looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;AppState&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isPresenter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;lastMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isConnected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;chosenName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This code &lt;em&gt;happened&lt;/em&gt; to work with the legacy compiler, but the IR compiler marks our problem: if our interface &lt;strong&gt;describes the exact shape of a &lt;em&gt;JavaScript object&lt;/em&gt;&lt;/strong&gt;, we need to &lt;strong&gt;mark the interface as &lt;code&gt;external&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The refactored code looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;AppState&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// . . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I made sure that all interfaces implementing &lt;code&gt;RState&lt;/code&gt; in my application were annotated with &lt;code&gt;external&lt;/code&gt; by using a &lt;a href="https://www.jetbrains.com/help/idea/structural-search-and-replace.html" rel="noopener noreferrer"&gt;&lt;strong&gt;structural search and replace&lt;/strong&gt;&lt;/a&gt;. If you're using IntelliJ IDEA 2021.1, you can copy an &lt;a href="https://gist.github.com/SebastianAigner/62119536f24597e630acfdbd14001b98" rel="noopener noreferrer"&gt;SSR template I prepared&lt;/a&gt; into your clipboard. To use it, open SSR via File | Find | Find Structurally [or Replace Structurally], click on the wrench icon, and select "Import Template from Clipboard". You can then click "Find" and "Replace All" to annotate all interfaces properly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Turn RProps into an external interface
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;RState&lt;/code&gt; isn't the only type that is affected by this change – similar problems appear when React properties (&lt;code&gt;RProps&lt;/code&gt;) aren't marked as external:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;codequiz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;100446&lt;/span&gt; &lt;span class="nx"&gt;Uncaught&lt;/span&gt; &lt;span class="nx"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$this$attrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_set_presenterStartGameHandler_&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;
    &lt;span class="nf"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;_no_name_provided__346&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke_547 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codequiz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;100446&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nf"&gt;eval &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codequiz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;101430&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;RElementBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attrs_0 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codequiz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;31443&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Analogously, this results from the &lt;code&gt;RProps&lt;/code&gt; definition being just a Kotlin &lt;code&gt;interface&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;LobbyProps&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isPresenter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;presenterStartGameHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;playerLoginHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;playerList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PlayerList&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isDisabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The IR-approved versions of this code uses an &lt;code&gt;external interface&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;LobbyProps&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// . . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once again, this change can just be repeated for all components defining &lt;code&gt;RProps&lt;/code&gt; interfaces in the Kotlin/JS application. This is easily automated via &lt;strong&gt;structural search and replace&lt;/strong&gt;, as described in the previous section. &lt;a href="https://gist.github.com/SebastianAigner/a47a77f5e519fc74185c077ba12624f9" rel="noopener noreferrer"&gt;Here is a template&lt;/a&gt; for auto-annotating your &lt;code&gt;RProps&lt;/code&gt; as &lt;code&gt;external&lt;/code&gt; – instructions for using SSR can be found in the previous section.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use external interfaces over data classes!
&lt;/h3&gt;

&lt;p&gt;If you've been using Kotlin's &lt;code&gt;class&lt;/code&gt; or &lt;code&gt;data class&lt;/code&gt; to create your &lt;code&gt;RProps&lt;/code&gt; or &lt;code&gt;RState&lt;/code&gt;s, you will need to do a similar refactoring. Code like this is invalid when using Kotlin/JS IR:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;CustomComponentState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RState&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Instead, use the following, refactored version.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;CustomComponentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Address limitations of external interfaces
&lt;/h3&gt;

&lt;p&gt;Compared to a Kotlin &lt;code&gt;interface&lt;/code&gt; or &lt;code&gt;class&lt;/code&gt;, there are a few &lt;strong&gt;limitations&lt;/strong&gt; when using &lt;code&gt;external interface&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to &lt;strong&gt;instantiate the interface from Kotlin code&lt;/strong&gt;, you will have to mark your properties as &lt;code&gt;var&lt;/code&gt; (&lt;code&gt;val&lt;/code&gt; will not work here). Also, certain Kotlin-specific constructs, such as &lt;strong&gt;function types with receivers, are prohibited&lt;/strong&gt; in external declarations.&lt;/p&gt;

&lt;p&gt;In our codebase, the latter showed up as a &lt;strong&gt;compile error&lt;/strong&gt; in an interface called &lt;code&gt;ButtonProps&lt;/code&gt;. Here, we define a property &lt;code&gt;inside&lt;/code&gt; which takes an extension function on the &lt;code&gt;StyledDOMBuilder&lt;/code&gt; type to define any components that should be rendered in the button:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ButtonProps&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;inside&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;StyledDOMBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BUTTON&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
    &lt;span class="c1"&gt;// . . .&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Since these functions with receivers are just &lt;strong&gt;syntactic sugar&lt;/strong&gt; for a function with an (implicitly named) parameter of the same type, we can refactor the &lt;code&gt;external interface&lt;/code&gt; and pass the &lt;code&gt;StyledDOMBuilder&lt;/code&gt; explicitly, resolving this problem:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;inside&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StyledDOMBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BUTTON&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As luck would have it, our &lt;strong&gt;callsite&lt;/strong&gt; was already structured so that this slightly changed style of function definition just works, so no change was needed there:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;styledButton&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inside&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;attrs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// . . .&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Create plain JS objects for interoperability
&lt;/h2&gt;

&lt;p&gt;Inside the definition of a React component, objects implementing &lt;code&gt;RState&lt;/code&gt; and &lt;code&gt;RProps&lt;/code&gt; &lt;strong&gt;already exist&lt;/strong&gt;, and we simply &lt;strong&gt;modify their properties&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When we &lt;strong&gt;create these objects&lt;/strong&gt; ourselves, we (currently still) need to be a bit careful. In CodeQuiz, we had the following problem passing values to an external &lt;a href="https://www.npmjs.com/package/react-minimal-pie-chart" rel="noopener noreferrer"&gt;&lt;code&gt;react-minimal-pie-chart&lt;/code&gt;&lt;/a&gt; component:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;PieChart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;attrs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;statistics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mapIndexed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;answerCounts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PiePoint&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Number $index"&lt;/span&gt;
                &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;answerCounts&lt;/span&gt;
                &lt;span class="c1"&gt;// . . .&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;toTypedArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;...and that even though &lt;code&gt;PiePoint&lt;/code&gt; is correctly specified as an &lt;code&gt;external interface&lt;/code&gt;. The specific issue here turned out to be a bit finicky:&lt;/p&gt;

&lt;p&gt;As of now, properties on a Kotlin &lt;code&gt;object&lt;/code&gt; implementing an &lt;code&gt;external interface&lt;/code&gt; are &lt;strong&gt;&lt;em&gt;accessible&lt;/em&gt;&lt;/strong&gt; from JavaScript, but, for example, they are &lt;a href="https://youtrack.jetbrains.com/issue/KT-31876" rel="noopener noreferrer"&gt;&lt;strong&gt;not &lt;em&gt;enumberable&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;. &lt;code&gt;react-minimal-pie-chart&lt;/code&gt; internally uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign" rel="noopener noreferrer"&gt;&lt;code&gt;Object.assign&lt;/code&gt;&lt;/a&gt; to copy around some of the data we pass as props. &lt;strong&gt;It loses our non-enumerable properties&lt;/strong&gt; in the process, which leads to some unexpected &lt;code&gt;undefined&lt;/code&gt;s at runtime. &lt;/p&gt;

&lt;p&gt;Until this problem is resolved (see the &lt;a href="https://youtrack.jetbrains.com/issue/KT-17683" rel="noopener noreferrer"&gt;corresponding YouTrack issue&lt;/a&gt;), the safe route right now is to &lt;strong&gt;generate plain JavaScript objects&lt;/strong&gt; ourselves.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;kotlin-wrappers&lt;/code&gt; actually include a &lt;strong&gt;helper function&lt;/strong&gt; called &lt;a href="https://github.com/JetBrains/kotlin-wrappers/blob/master/kotlin-extensions/src/main/kotlin/kotlinext/js/Helpers.kt" rel="noopener noreferrer"&gt;&lt;code&gt;jsObject&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt; which is useful for creating such objects. The same snippet using these plain JavaScript objects looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;PieChart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;attrs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;statistics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mapIndexed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;answerCounts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;jsObject&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PiePoint&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Number $index"&lt;/span&gt;
                &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;answerCounts&lt;/span&gt;
                &lt;span class="c1"&gt;// . . .&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;toTypedArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Since in a plain JavaScript object, all properties are enumerable, our charting library now works properly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Help the DCE via @JsExport!
&lt;/h2&gt;

&lt;p&gt;Dead Code Elimination (DCE) is the part of the Kotlin/JS IR compiler that helps &lt;strong&gt;keep your compiled production artifacts small&lt;/strong&gt;. It's responsible for analyzing the Kotlin code for any pieces of code that aren't being used anywhere, and subsequently deleting them.&lt;/p&gt;

&lt;p&gt;When packaging our application for production (which is when DCE is executed, e.g. via &lt;code&gt;browserProductionRun&lt;/code&gt; or &lt;code&gt;jsBrowserDistribution&lt;/code&gt;), this can present a &lt;strong&gt;problem&lt;/strong&gt; for our &lt;strong&gt;React components&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Consider the following &lt;code&gt;Evaluation&lt;/code&gt; class from our project:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Evaluation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;EvaluationProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;EvaluationProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;RBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The only way this class is ever referenced via its &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-class/" rel="noopener noreferrer"&gt;&lt;code&gt;KClass&lt;/code&gt;&lt;/a&gt;, when we tell React to render this component:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Evaluation&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;attrs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// . . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As of now, the IR DCE tries to be a bit too clever for its own good. &lt;strong&gt;It removes the contents of our class&lt;/strong&gt; practically entirely (from its perspective, none of it, besides the type itself, is being used after all!). This causes the (unfortunately quite cryptic) error &lt;code&gt;TypeError: r.render is not a function&lt;/code&gt; (or something similar).&lt;/p&gt;

&lt;p&gt;To turn this error message into something a bit more actionable, we can (temporarily!) &lt;strong&gt;enable webpack's development mode&lt;/strong&gt; in our Gradle build file (&lt;code&gt;build.gradle(.kts)&lt;/code&gt;), which turns off the name minification:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;browser&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;commonWebpackConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// . . .&lt;/span&gt;
        &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jetbrains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gradle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;KotlinWebpackConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Mode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DEVELOPMENT&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For now, we need to make sure our component doesn't get removed, we can &lt;strong&gt;mark the class&lt;/strong&gt; with &lt;code&gt;@JsExport&lt;/code&gt;. Then, DCE will not touch it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@JsExport&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Evaluation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;EvaluationProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;EvaluationProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;RBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;(As a small sidenote: declarations marked as &lt;code&gt;external&lt;/code&gt;, such as an &lt;code&gt;external interface&lt;/code&gt;, are always treated as reachable by DCE, and don't need this treatment. &lt;a href="https://github.com/JetBrains/kotlin-wrappers/blob/master/kotlin-react/README.md#creating-a-react-function-component-with-kotlin" rel="noopener noreferrer"&gt;Functional components&lt;/a&gt; are also not affected, because their usage site doesn't refer to the &lt;code&gt;::class&lt;/code&gt;, but to the variable holding the component directly.)&lt;/p&gt;

&lt;p&gt;In the case of &lt;code&gt;kotlin-react&lt;/code&gt;, there are still &lt;strong&gt;some rough edges&lt;/strong&gt;, like the warning &lt;code&gt;Exported declaration uses non-exportable super type: RComponent&lt;/code&gt;. Together with making this kind of "workaround" obsolete, these are topics that still need addressing before the IR compiler becomes the default choice.&lt;/p&gt;

&lt;p&gt;You can find a Structural Search and Replace template for this change &lt;a href="https://gist.github.com/SebastianAigner/b06f50b1448f6466775b0df14fb2b35f" rel="noopener noreferrer"&gt;right here&lt;/a&gt;. Find instructions on how to apply this automated replacement to your project in one of the previous paragraphs.&lt;/p&gt;

&lt;p&gt;This is definitely one of the trickier issues to find, because it &lt;strong&gt;only manifests in production artifacts&lt;/strong&gt; (when DCE is actually executed). For this reason, it's important to &lt;strong&gt;test your production artifacts&lt;/strong&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  Fixing dependencies on default exports
&lt;/h2&gt;

&lt;p&gt;Our app uses a few external React components which we get from npm, including &lt;code&gt;react-minimal-pie-chart&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="nx"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Unexpected&lt;/span&gt; &lt;span class="nx"&gt;keyword&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;File&lt;/span&gt; &lt;span class="nx"&gt;was&lt;/span&gt; &lt;span class="nx"&gt;processed&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;these&lt;/span&gt; &lt;span class="nx"&gt;loaders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;cjs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;may&lt;/span&gt; &lt;span class="nx"&gt;need&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;additional&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;handle&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;these&lt;/span&gt; &lt;span class="nx"&gt;loaders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$module$react_dom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$module$styled_components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$module$react_minimal_pie_chart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$module$react_player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We wrote the following external declaration for the component provided by this package, which worked for our used version, &lt;code&gt;5.0.2&lt;/code&gt;, beforehand, but not with IR:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;JsModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"react-minimal-pie-chart"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;JsNonModule&lt;/span&gt;
&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PieChartProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// . . .&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@JsName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;PieChart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RClass&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PieChartProps&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, we actually hit &lt;strong&gt;a bug in the IR compiler&lt;/strong&gt;! It currently does not treat &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export#description" rel="noopener noreferrer"&gt;&lt;code&gt;default&lt;/code&gt;&lt;/a&gt; as a reserved identifier. This causes a conflict when the library uses this identifier for its exports:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Chart&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Chart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://youtrack.jetbrains.com/issue/KT-41650" rel="noopener noreferrer"&gt;An issue&lt;/a&gt; exists to turn &lt;code&gt;default&lt;/code&gt; into a reserved identifier, and this point will hopefully be addressed soon. Until then, the &lt;strong&gt;workaround&lt;/strong&gt; is to wrap the definition in an external object, like so:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PieChartProps&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// . . .&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@JsModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"react-minimal-pie-chart"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@JsNonModule&lt;/span&gt;
&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;PieChart&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RClass&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PieChartProps&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At the usage site for the component, we now use the &lt;code&gt;PieChart.default&lt;/code&gt; value instead of the &lt;code&gt;PieChart&lt;/code&gt; value previously:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;PieChart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;attrs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// . . .&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Fix library code
&lt;/h2&gt;

&lt;p&gt;After fixing all of the other problems, I noticed a special case where the app would throw the following error:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Uncaught&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`props.dangerouslySetInnerHTML`&lt;/span&gt; &lt;span class="nx"&gt;must&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="s2"&gt;`{__html: ...}`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Please&lt;/span&gt; &lt;span class="nx"&gt;visit&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//reactjs.org/link/dangerously-set-inner-html for more information.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It took me a while to find the culprit, but I remembered that there was a place where we explicitly allowed HTML-formatted rich text in our application, and are using &lt;code&gt;unsafe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RBuilder&lt;/span&gt;&lt;span class="p"&gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="n"&gt;answerText&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It turns out that &lt;code&gt;kotlin-wrappers&lt;/code&gt; actually &lt;strong&gt;contained a small mistake&lt;/strong&gt; in its own interoperation code: it used a &lt;code&gt;class&lt;/code&gt; instead of an &lt;code&gt;external interface&lt;/code&gt; for their &lt;code&gt;InnerHTML&lt;/code&gt; object – which is used to implement &lt;code&gt;attrs.unsafe&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/JetBrains/kotlin-wrappers/pull/416" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Make InnerHTML external interface
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#416&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/SebastianAigner" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F2178959%3Fv%3D4" alt="SebastianAigner avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/SebastianAigner" rel="noopener noreferrer"&gt;SebastianAigner&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/JetBrains/kotlin-wrappers/pull/416" rel="noopener noreferrer"&gt;&lt;time&gt;Feb 18, 2021&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Fixes IR problem where unsafe throws&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://youtrack.jetbrains.com/issue/KT-45021" rel="nofollow noopener noreferrer"&gt;https://youtrack.jetbrains.com/issue/KT-45021&lt;/a&gt;&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/JetBrains/kotlin-wrappers/pull/416" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;This was a great point to &lt;strong&gt;make a small open-source contribution&lt;/strong&gt; in the form of a pull request (and get the code improved further just &lt;a href="https://github.com/JetBrains/kotlin-wrappers/pull/418" rel="noopener noreferrer"&gt;hours later&lt;/a&gt;)!&lt;/p&gt;

&lt;h2&gt;
  
  
  Petition library authors to support IR
&lt;/h2&gt;

&lt;p&gt;Luckily, all the libraries we are using in the project (including &lt;a href="https://ktor.io/" rel="noopener noreferrer"&gt;Ktor Clients&lt;/a&gt; and &lt;a href="https://github.com/Kotlin/kotlinx.serialization" rel="noopener noreferrer"&gt;kotlinx.serialization&lt;/a&gt;) already support the Kotlin/JS IR compiler, and they provide artifacts that work with both backends. And there is a number of other libraries that already offer artifacts compatible with the IR compiler, like &lt;a href="https://www.fritz2.dev/" rel="noopener noreferrer"&gt;fritz2&lt;/a&gt;, &lt;a href="https://github.com/korlibs/korge" rel="noopener noreferrer"&gt;KorGE&lt;/a&gt;, &lt;a href="https://github.com/Kodein-Framework/Kodein-DI" rel="noopener noreferrer"&gt;Kodein-DI&lt;/a&gt;, and more.&lt;/p&gt;

&lt;p&gt;If you're using a Kotlin/JS library that currently does not ship IR-compatible artifacts, it might be a good idea to &lt;strong&gt;catch the maintainer's attention&lt;/strong&gt;, and maybe &lt;strong&gt;help out&lt;/strong&gt; yourself to ensure that your favorite libraries work well with the new compiler infrastructure. To make sure libraries can support both legacy and IR backends at the same time, there is also a mechanism for &lt;a href="https://kotlinlang.org/docs/js-ir-compiler.html#authoring-libraries-for-the-ir-compiler-with-backwards-compatibility" rel="noopener noreferrer"&gt;authoring libraries with backwards compatibility&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're a &lt;strong&gt;library author&lt;/strong&gt;, and want to learn more about supporting the Kotlin/JS IR backend, please do not hesitate to reach out on the &lt;a href="http://kotl.in/slack" rel="noopener noreferrer"&gt;Kotlinlang Slack&lt;/a&gt;. You can either contact me directly, or get input from the team and community in the &lt;code&gt;#javascript&lt;/code&gt; channel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;The new IR compiler introduces some changes that might require action from you – especially in places where Kotlin code meets the JavaScript platform. I hope this post helps diagnose some of these behavior changes, so that you can experience all the &lt;strong&gt;exciting stuff&lt;/strong&gt; the new compiler brings as soon as possible.&lt;/p&gt;

&lt;p&gt;If you encounter issues during your migration to the IR backend, share them with the team. We're happy to help, and rely on your feedback to make sure we can iron out any remaining problems as soon as possible. The easiest way to do this is to log your problems in the official Kotlin &lt;a href="http://kotl.in/issue" rel="noopener noreferrer"&gt;issue tracker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Give the Kotlin/JS IR compiler a try in your projects, and prepare yourself for the future! &lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Tips and tricks for your Kotlin code explorations</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Wed, 03 Mar 2021 13:27:40 +0000</pubDate>
      <link>https://dev.to/kotlin/tips-and-tricks-for-your-kotlin-code-explorations-40i9</link>
      <guid>https://dev.to/kotlin/tips-and-tricks-for-your-kotlin-code-explorations-40i9</guid>
      <description>&lt;p&gt;This blog post accompanies a video from our &lt;strong&gt;YouTube series&lt;/strong&gt; which you can find on our &lt;a href="https://kotl.in/video" rel="noopener noreferrer"&gt;Kotlin YouTube channel&lt;/a&gt;, or &lt;strong&gt;watch here&lt;/strong&gt; directly!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/DIHlq_Q0vKM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We’re going to take a look at some &lt;strong&gt;handy tips and tricks&lt;/strong&gt; to help you &lt;strong&gt;explore Kotlin code&lt;/strong&gt;, no matter whether it's your own code or the code from the Kotlin standard library or any of your other dependencies. They will equip you to &lt;strong&gt;discover&lt;/strong&gt; some of the &lt;strong&gt;goodies&lt;/strong&gt; in the code you’re working with on your own.&lt;/p&gt;

&lt;p&gt;Working with Kotlin means we have some &lt;strong&gt;powerful companions&lt;/strong&gt; by our side - &lt;a href="https://www.jetbrains.com/idea/" rel="noopener noreferrer"&gt;IntelliJ IDEA&lt;/a&gt; and &lt;a href="https://developer.android.com/studio" rel="noopener noreferrer"&gt;Android Studio&lt;/a&gt; - that help us in every step of the development process. Let's get to know them a little better and &lt;strong&gt;become more productive&lt;/strong&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading and writing code
&lt;/h2&gt;

&lt;p&gt;So – how do &lt;em&gt;I&lt;/em&gt; &lt;strong&gt;read and understand&lt;/strong&gt; Kotlin code that I encounter and modify?&lt;/p&gt;

&lt;h3&gt;
  
  
  Annotating code with types and names: Inlay hints
&lt;/h3&gt;

&lt;p&gt;A big helper I rely on every day is these little grey bobbles wherever variable names or types appear, called &lt;strong&gt;&lt;a href="https://www.jetbrains.com/help/idea/inlay-hints.html" rel="noopener noreferrer"&gt;inlay hints&lt;/a&gt;&lt;/strong&gt;, and honestly, I don’t want to read code without them. They give us information about &lt;strong&gt;types&lt;/strong&gt; and &lt;strong&gt;parameter names&lt;/strong&gt;, right where that information is most useful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FeRMFtzt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FeRMFtzt.gif" alt="Inlay hints give handy information about types and names."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We enable those in our preferences under &lt;em&gt;Editor&lt;/em&gt; &amp;gt; &lt;em&gt;Inlay Hints&lt;/em&gt; &amp;gt; &lt;em&gt;Kotlin&lt;/em&gt;. (I have all of them enabled, but toggles are available for fine-grained control.)&lt;/p&gt;

&lt;h4&gt;
  
  
  Inlay hints for chained operations
&lt;/h4&gt;

&lt;p&gt;These inlay hints help me a lot! For example, when I’m chaining a bunch of operations, they give me a &lt;strong&gt;quick check&lt;/strong&gt; whether I am creating the &lt;strong&gt;correct type&lt;/strong&gt; at the end:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FCBFax5F.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FCBFax5F.gif" alt="Adding a .toString() to the end of a call chain changes the type hint accordingly"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Inlay hints for lambdas and DSLs
&lt;/h4&gt;

&lt;p&gt;Inlay hints are also awesome whenever we encounter &lt;strong&gt;lambdas&lt;/strong&gt;, especially &lt;strong&gt;&lt;a href="https://kotlinlang.org/docs/lambdas.html#function-literals-with-receiver" rel="noopener noreferrer"&gt;lambdas with receivers&lt;/a&gt;&lt;/strong&gt;, because they give us information about &lt;strong&gt;variables&lt;/strong&gt; that are implicitly in scope, or which &lt;strong&gt;receiver&lt;/strong&gt; your lambda actually provides.&lt;/p&gt;

&lt;p&gt;Especially if we are working on a project that makes heavy use of &lt;a href="https://kotlinlang.org/docs/type-safe-builders.html" rel="noopener noreferrer"&gt;Kotlin’s &lt;strong&gt;DSL functionality&lt;/strong&gt;&lt;/a&gt;, these hints can help &lt;strong&gt;demystify&lt;/strong&gt; some of these APIs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fulxb1bvtabepqvj5i0dz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fulxb1bvtabepqvj5i0dz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Inlay hints for the Kotlin Gradle DSL
&lt;/h4&gt;

&lt;p&gt;Oh, and as a little hint – if we are using the &lt;strong&gt;&lt;a href="https://docs.gradle.org/current/userguide/kotlin_dsl.html" rel="noopener noreferrer"&gt;Gradle Kotlin DSL&lt;/a&gt;&lt;/strong&gt; (so if our build file ends in .kts), these inlay hints also work here!&lt;/p&gt;

&lt;p&gt;For someone who tried to avoid touching Gradle for quite a while myself, I’d say that the Kotlin Gradle DSL, together with these inlay hints, have helped me &lt;strong&gt;understand&lt;/strong&gt; how the Kotlin DSL for Gradle works, what &lt;strong&gt;functionality&lt;/strong&gt; is available in what scope, and so on:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyxrgmedl2ycqlfi0p1e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyxrgmedl2ycqlfi0p1e.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try using inlay hints yourself&lt;/strong&gt;! Maybe you'll fall in love just like I did.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code completion (&lt;code&gt;⌃&lt;/code&gt; &lt;code&gt;Space&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;In my opinion, code completion is the &lt;strong&gt;number one way&lt;/strong&gt; in IntelliJ IDEA or Android Studio to &lt;strong&gt;discover a Kotlin API&lt;/strong&gt;. We know the drill – we &lt;strong&gt;put a dot&lt;/strong&gt; behind a symbol, and &lt;strong&gt;get some suggestions&lt;/strong&gt; of what we might want to call:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9axn4ljd2kf0vpuney0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9axn4ljd2kf0vpuney0j.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But code completion &lt;strong&gt;doesn't always pop up naturally&lt;/strong&gt;. For example, when you're inside a lambda function. Via inlay hints, we might be able to determine that there's an implicit &lt;code&gt;this&lt;/code&gt; in scope – and we could type &lt;code&gt;this.&lt;/code&gt; and get code completion. But there's also a nicer (and easier) way.&lt;/p&gt;

&lt;p&gt;We just press &lt;code&gt;⌃&lt;/code&gt; &lt;code&gt;Space&lt;/code&gt; (&lt;code&gt;Ctrl&lt;/code&gt; &lt;code&gt;Space&lt;/code&gt; on Win/Linux) to manually &lt;strong&gt;invoke completion&lt;/strong&gt; based on our current scope. And &lt;strong&gt;this works&lt;/strong&gt; practically &lt;strong&gt;everywhere&lt;/strong&gt; – whether we are inside a builder block or returning to an unfinished statement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmdaax1k4pyphnkd6jht9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmdaax1k4pyphnkd6jht9.png" alt="Using Ctrl-Space to invoke completion."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IntelliJ IDEA's &lt;a href="https://www.jetbrains.com/help/idea/productivity-guide.html" rel="noopener noreferrer"&gt;productivity guide&lt;/a&gt; tells me I've used the feature over 2400 times, and it's one of the most important tools in the belt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parameter info: Type popup (&lt;code&gt;⌘&lt;/code&gt; &lt;code&gt;P&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;When we first type out a function with &lt;strong&gt;parentheses&lt;/strong&gt;, we get a little &lt;strong&gt;hint bubble&lt;/strong&gt; that tells us parameters that the function accepts. However, this popup only appears the &lt;strong&gt;first time&lt;/strong&gt; we write those parentheses – when we &lt;strong&gt;jump away&lt;/strong&gt; with our cursor and return to our function later, we might want to &lt;strong&gt;see this information again&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To magically &lt;strong&gt;summon the parameter info popup&lt;/strong&gt; again, we simply press &lt;code&gt;⌘&lt;/code&gt; &lt;code&gt;P&lt;/code&gt; (&lt;code&gt;Ctrl&lt;/code&gt; &lt;code&gt;P&lt;/code&gt; on Win/Linux):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwm7kn5u7bd2jdsc1can5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwm7kn5u7bd2jdsc1can5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The popup also shows default parameters, overloads &amp;amp; co. As such, it can also help us &lt;strong&gt;discover new functionality&lt;/strong&gt; on already existing code – like additional parameters we might still want to add to &lt;strong&gt;adjust the behavior&lt;/strong&gt; of any functions we call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Documentation (&lt;code&gt;F1&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;If we hit &lt;code&gt;F1&lt;/code&gt; (&lt;code&gt;Ctrl&lt;/code&gt; &lt;code&gt;Q&lt;/code&gt; on Win/Linux), IntelliJ IDEA will show us a little text blurb explaining what a method is supposed to do – some &lt;strong&gt;quick documentation&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;We can actually &lt;strong&gt;pin this window&lt;/strong&gt; to the side of our IDE via the three little dots &lt;code&gt;⋮&lt;/code&gt; in the pop-over. From there, we can select the option “&lt;strong&gt;auto-update from source&lt;/strong&gt;,” reachable by the small cogwheel icon ⚙️. With this enabled, we always get up-to-date information on the side of our IDE about the symbol the cursor is currently over.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fgsnt9p2ur6whc3ao7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fgsnt9p2ur6whc3ao7w.png" alt="Auto-updating quick documentation, right next to the code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigating through code
&lt;/h2&gt;

&lt;p&gt;Your IDE also empowers you when it comes to &lt;strong&gt;moving between pieces of code&lt;/strong&gt;, usages and declarations, and more. Let's take a closer look!&lt;/p&gt;

&lt;h3&gt;
  
  
  Go to declaration or usages (&lt;code&gt;⌘&lt;/code&gt; &lt;code&gt;Click&lt;/code&gt; / &lt;code&gt;B&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The shortcut &lt;code&gt;⌘&lt;/code&gt; &lt;code&gt;Click&lt;/code&gt; / &lt;code&gt;B&lt;/code&gt; (&lt;code&gt;Ctrl&lt;/code&gt; &lt;code&gt;Click&lt;/code&gt; / &lt;code&gt;B&lt;/code&gt; on Win/Linux) is known by its formal title “&lt;strong&gt;Go to declaration or usages&lt;/strong&gt;”. As you may have guessed, it’s a two-way shortcut:&lt;/p&gt;

&lt;p&gt;When we &lt;strong&gt;click on the usage of a symbol&lt;/strong&gt; – a variable, a place where we’re constructing a new object, invoking a function, or implementing an interface – this shortcut will &lt;strong&gt;send us to the definition&lt;/strong&gt; of what we just clicked.&lt;/p&gt;

&lt;p&gt;And vice-versa, when we click on a &lt;strong&gt;symbol declaration&lt;/strong&gt; – so a place where we’re declaring a variable, an interface, a class, or a function, this is going to give us &lt;strong&gt;a list of all places where that symbol is being used&lt;/strong&gt; in our project.&lt;/p&gt;

&lt;p&gt;This shortcut is an easy way to &lt;strong&gt;reveal interesting information&lt;/strong&gt; about our code and the code we depend on. I find &lt;strong&gt;stepping into a library&lt;/strong&gt; especially useful:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FbVQFHWd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FbVQFHWd.gif" alt="Stepping into a library via shortcut."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can look at the code we’re calling, &lt;strong&gt;learn something&lt;/strong&gt; from its implementation and structure, and we can &lt;strong&gt;immerse ourselves&lt;/strong&gt; even deeper.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rendered documentation
&lt;/h3&gt;

&lt;p&gt;IntelliJ IDEA and Android Studio actually have something called “&lt;a href="https://www.jetbrains.com/help/idea/working-with-code-documentation.html#toggle-rendered-view" rel="noopener noreferrer"&gt;Rendered documentation&lt;/a&gt;”. This makes it more comfortable to read documentation blocks in code by changing the font and making the contrast between code and documentation even stronger.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure tool window
&lt;/h3&gt;

&lt;p&gt;IntelliJ and Android Studio allow us to look at our currently opened file's structure, which helps us &lt;strong&gt;discover interesting parts quicker&lt;/strong&gt;. We can enable the structure tool window via View &amp;gt; Tool Windows &amp;gt; Structure. This pops open information about the current file, which we can use as a &lt;strong&gt;navigation helper&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FLdPinqA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FLdPinqA.gif" alt="Navigating a file via the structure tool window"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Searching (and finding)
&lt;/h3&gt;

&lt;p&gt;If we can’t find what we’re looking for, we can always go back to the &lt;strong&gt;text search function&lt;/strong&gt;. In IntelliJ IDEA and Android Studio, we can reach “Find in Files” via &lt;code&gt;⌘&lt;/code&gt; &lt;code&gt;⇧&lt;/code&gt; &lt;code&gt;F&lt;/code&gt; (&lt;code&gt;Ctrl&lt;/code&gt; &lt;code&gt;Shift&lt;/code&gt; &lt;code&gt;F&lt;/code&gt; on Win/Linux).&lt;/p&gt;

&lt;p&gt;By default, this function only searches for text occurrences in our own code, not the code of our dependencies. However, we can set our search scope to include "Projects and Libraries" to widen where to look for text snippets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bdam86y8x2jfod67zc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bdam86y8x2jfod67zc3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Structural search
&lt;/h4&gt;

&lt;p&gt;There’s also the so-called &lt;strong&gt;&lt;a href="https://www.jetbrains.com/help/idea/structural-search-and-replace.html" rel="noopener noreferrer"&gt;structural search&lt;/a&gt;&lt;/strong&gt;, which is a bit of a specialized tool when it comes to exploring. It allows us to find &lt;strong&gt;constructs matching a specific schema&lt;/strong&gt;, for example finding functions that have exactly one parameter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhv4z4p86z2zlph5kyduu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhv4z4p86z2zlph5kyduu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might not use this one as often. But it’s always good to have heard about the fact that it exists – you never know when that knowledge might come in handy, and then you can look into the topic a bit more deeply.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go and explore!
&lt;/h2&gt;

&lt;p&gt;I hope you learned something new. If you have some more must-have settings, shortcuts, or whatever, feel free to &lt;strong&gt;share them with me&lt;/strong&gt;, either here, on &lt;a href="http://kotl.in/video" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, or &lt;a href="https://twitter.com/sebi_io" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are tons of other &lt;strong&gt;productivity shortcuts&lt;/strong&gt; in your Kotlin IDE. If you’re interested in more of them, check out Trisha Gee's video covering the 15 IntelliJ IDEA shortcuts:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/QYO5_riePOQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Alternatively (or additionally), grab yourself a &lt;a href="https://resources.jetbrains.com/storage/products/intellij-idea/docs/IntelliJIDEA_ReferenceCard.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;virtual keymap overview&lt;/strong&gt;&lt;/a&gt;, which has all the most-used shortcuts for the operating system of your choice!&lt;/p&gt;

&lt;p&gt;Try integrating your new knowledge when you work with Kotlin code the next time. &lt;strong&gt;Have fun exploring!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>productivity</category>
      <category>programming</category>
      <category>tools</category>
    </item>
    <item>
      <title>Hosting Kotlin/JS on GitHub Pages via GitHub Actions</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Fri, 05 Feb 2021 12:16:28 +0000</pubDate>
      <link>https://dev.to/kotlin/hosting-kotlin-js-on-github-pages-via-github-actions-3gep</link>
      <guid>https://dev.to/kotlin/hosting-kotlin-js-on-github-pages-via-github-actions-3gep</guid>
      <description>&lt;p&gt;&lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;GitHub Pages&lt;/a&gt; is an easy way to &lt;strong&gt;host your Kotlin/JS application&lt;/strong&gt; - and in combination with the &lt;strong&gt;continuous integration&lt;/strong&gt; service &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;, you can easily set up a smooth development (and deployment!) experience for your projects. Read on to learn how you can &lt;strong&gt;build and test your application on GitHub's CI&lt;/strong&gt;, and get your &lt;strong&gt;Kotlin/JS web apps published for free&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this post, we are going to configure GitHub Actions and Pages so that &lt;strong&gt;new code&lt;/strong&gt; pushed to our repository or added via pull request &lt;strong&gt;is automatically validated&lt;/strong&gt; (by having the project built and our tests run on GitHub's servers), and code pushed to the main branch of our project is automatically made &lt;strong&gt;available to the public&lt;/strong&gt; (by generating and publishing production artifacts of our app).&lt;/p&gt;

&lt;p&gt;To achieve this, we are going to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up a quick Kotlin/JS project&lt;/li&gt;
&lt;li&gt;
Share its code on GitHub (via IntelliJ IDEA's Git integration)&lt;/li&gt;
&lt;li&gt;Set up GitHub Actions' workflow YAML&lt;/li&gt;
&lt;li&gt;Set up GitHub pages to work with the result of our Actions workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you already know the basics, and want to skip straight to the configuration section, click here – or &lt;a href="https://github.com/SebastianAigner/kotlin-js-on-gh-pages" rel="noopener noreferrer"&gt;find the sample project directly on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up our sample Kotlin/JS application &lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To &lt;em&gt;deploy&lt;/em&gt; a project, we must first &lt;em&gt;have&lt;/em&gt; a project. For this demo, I will use an &lt;strong&gt;example generated via project wizard&lt;/strong&gt; – if you already have a Kotlin/JS application you would like to deploy, feel free to skip ahead and use it instead.&lt;/p&gt;

&lt;p&gt;A boilerplate Kotlin/JS project is quickly generated in &lt;a href="https://www.jetbrains.com/idea/" rel="noopener noreferrer"&gt;IntelliJ IDEA&lt;/a&gt; by navigating to File | New | Project..., selecting "Kotlin" in the sidebar, and choosing a &lt;strong&gt;project template&lt;/strong&gt; in the "Kotlin/JS" section (I'm choosing a React project). We just need to make sure that a Project JDK is selected. For everything else, the default settings are fine and don't need to be adjusted:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1nzk5keyrms4u7bh619e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1nzk5keyrms4u7bh619e.png" alt="new-project-wizard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have a basic project, let's start by &lt;strong&gt;getting it on GitHub&lt;/strong&gt; - creating a repository and pushing our code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting our code on GitHub &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We could, of course, use &lt;a href="https://guides.github.com/activities/hello-world/#repository" rel="noopener noreferrer"&gt;GitHub's web interface&lt;/a&gt; to set up our repository, and wire up our local repository manually – but &lt;strong&gt;&lt;a href="https://www.jetbrains.com/help/idea/version-control-integration.html" rel="noopener noreferrer"&gt;IntelliJ IDEA's Version Control Integration&lt;/a&gt;&lt;/strong&gt; makes it &lt;strong&gt;even smoother&lt;/strong&gt; to move our project code into a new GitHub Repository. We simply select "&lt;strong&gt;Share Project on GitHub&lt;/strong&gt;" in the "VCS" tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe5y09kdv0ube2dmztwq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe5y09kdv0ube2dmztwq9.png" alt="share project on github"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this is your first time using this feature, IntelliJ IDEA might ask you to &lt;strong&gt;authenticate&lt;/strong&gt; using your GitHub account. You then get to specify your repository name, its visibility (private/public), and can provide a short description that will show up on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi42fc1w8jug5l95wafiv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi42fc1w8jug5l95wafiv.png" alt="share proj"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once confirmed, IntelliJ IDEA will create a GitHub project for you, and show you the "Add Files For Initial Commit" window, which we can simply accept by pressing "Add":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F29g49u26awwu8ebz8ig3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F29g49u26awwu8ebz8ig3.png" alt="initial commit including gitignore"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you might have noticed, IntelliJ IDEA makes our life a bit easier here by &lt;strong&gt;auto-generating&lt;/strong&gt; a default set of &lt;code&gt;.gitignore&lt;/code&gt; files, making sure that any files which shouldn't be checked into source control (such as build artifacts or local configurations) are &lt;strong&gt;correctly ignored&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once the commit is finished, we see a small notification bubble containing a &lt;strong&gt;link to our GitHub repository&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fst0uwzx0v3qi9s66k4w6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fst0uwzx0v3qi9s66k4w6.png" alt="success"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up GitHub Actions &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Time to set up GitHub Actions! Actions will be responsible for &lt;strong&gt;building and testing&lt;/strong&gt; our project – turning our Kotlin source files into &lt;code&gt;.js&lt;/code&gt; and &lt;code&gt;.html&lt;/code&gt; artifacts, running any unit tests we might have, and copying files into the right location for deployment on GitHub Pages (a branch called &lt;code&gt;gh-pages&lt;/code&gt; by convention). We configure Actions using so-called &lt;a href="https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions" rel="noopener noreferrer"&gt;&lt;strong&gt;workflows&lt;/strong&gt;&lt;/a&gt;, which are YAML configuration files containing instructions on how to transform and build code.&lt;/p&gt;

&lt;p&gt;GitHub looks for workflows in the &lt;code&gt;.github/workflows&lt;/code&gt; directory, so let's create this directory structure at our project's root. Inside, let's create a new file called &lt;code&gt;build-and-publish-kjs.yml&lt;/code&gt;, and add the following configuration to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and Publish&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test and Build&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="c1"&gt;# Setup Java 1.8 environment for the next steps&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Java&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.8&lt;/span&gt;

      &lt;span class="c1"&gt;# Check out current repository&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Fetch Sources&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="c1"&gt;# Build application&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test and Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./gradlew build&lt;/span&gt;

      &lt;span class="c1"&gt;# If main branch update, deploy to gh-pages&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main'&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;JamesIves/github-pages-deploy-action@3.7.1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;BRANCH&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gh-pages&lt;/span&gt; &lt;span class="c1"&gt;# The branch the action should deploy to.&lt;/span&gt;
          &lt;span class="na"&gt;FOLDER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/distributions&lt;/span&gt; &lt;span class="c1"&gt;# The folder the action should deploy.&lt;/span&gt;
          &lt;span class="na"&gt;CLEAN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# Automatically remove deleted files from the deploy branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Understanding our Action YAML
&lt;/h3&gt;

&lt;p&gt;We could just use this configuration as is, and move on to the next step – but it's always good to try and understand what's going on in our project. And while the YAML configuration reads quite naturally, I still want to quickly look at this configuration file section by section (Additionally, feel free to consult the &lt;a href="https://docs.github.com/en/actions/learn-github-actions" rel="noopener noreferrer"&gt;GitHub Actions documentation&lt;/a&gt; for more information):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We first give our workflow a &lt;code&gt;name&lt;/code&gt; – in this case, &lt;code&gt;Build and Publish&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Next, we define the triggers for this workflow – what events &lt;strong&gt;kick off&lt;/strong&gt; this process. Because we want to make sure that pushed code always compiles, and that pull requests are also fine, we set the value to &lt;code&gt;push&lt;/code&gt; and &lt;code&gt;pull_request&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Next, we define a &lt;code&gt;job&lt;/code&gt;, which &lt;strong&gt;groups&lt;/strong&gt; the different steps we want to run in a given environment (in our case, &lt;code&gt;ubuntu-latest&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Now, we define the different &lt;code&gt;steps&lt;/code&gt; our build needs to go through:

&lt;ul&gt;
&lt;li&gt;The Kotlin compiler needs Java to be present, so we use a &lt;a href="https://github.com/actions/setup-java" rel="noopener noreferrer"&gt;predefined GitHub Action&lt;/a&gt; to &lt;strong&gt;install Java &lt;code&gt;1.8&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;We use &lt;a href="https://github.com/actions/checkout" rel="noopener noreferrer"&gt;another predefined Action&lt;/a&gt; to &lt;strong&gt;check out the code&lt;/strong&gt; for our project.&lt;/li&gt;
&lt;li&gt;We run the &lt;code&gt;./gradlew build&lt;/code&gt; command. &lt;code&gt;build&lt;/code&gt; is a &lt;strong&gt;standard lifecycle&lt;/strong&gt; task for Kotlin/JS projects which installs all dependencies from npm and Gradle, compiles the application, and runs any tests included in the project.&lt;/li&gt;
&lt;li&gt;Lastly, we use &lt;a href="https://github.com/JamesIves/github-pages-deploy-action" rel="noopener noreferrer"&gt;another Action&lt;/a&gt; to &lt;strong&gt;deploy our project&lt;/strong&gt; to GitHub Pages – but &lt;strong&gt;only if the workflow is running on the &lt;code&gt;master&lt;/code&gt; or &lt;code&gt;main&lt;/code&gt; branch&lt;/strong&gt; (we don't want development branches to be deployed to the public!). We point this action to the &lt;code&gt;build/distributions&lt;/code&gt; folder, which is where building a Kotlin/JS project creates the final &lt;code&gt;.js&lt;/code&gt; and &lt;code&gt;.html&lt;/code&gt; artifacts.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: This workflow &lt;strong&gt;builds and tests all commits and pull requests&lt;/strong&gt; – if the commit is on the &lt;code&gt;master&lt;/code&gt; or &lt;code&gt;main&lt;/code&gt; branch, the changes are prepared for &lt;strong&gt;publishing via Pages&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Committing the workflow file
&lt;/h3&gt;

&lt;p&gt;To enable our newly created workflow in the GitHub project, we &lt;strong&gt;commit and push&lt;/strong&gt; our new &lt;code&gt;build-and-publish-kjs.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you do this via IntelliJ IDEA's "Commit and Push" functionality, please note that, depending on how your GitHub account is authenticated, you may encounter the following error when pushing a commit containing workflow files to your GitHub repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: failed to push some refs to 'https://github.com/SebastianAigner/kotlin-js-on-github-pages.git'
To https://github.com/SebastianAigner/kotlin-js-on-github-pages.git
!   refs/heads/master:refs/heads/master [remote rejected] (refusing to allow an OAuth App to create or update workflow `.github/workflows/build-and-publish-kjs.yml` without `workflow` scope)
Done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is because of an OAuth issue with GitHub requiring a specific scope to push workflow-modifying commits. You can find more info on it and &lt;a href="https://youtrack.jetbrains.com/issue/IDEA-247361" rel="noopener noreferrer"&gt;vote on it here&lt;/a&gt;. Instead, you can commit the code via the terminal integrated in IntelliJ IDEA, using &lt;code&gt;git push origin master&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh3rijixf4qmhfsezqpc4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh3rijixf4qmhfsezqpc4.png" alt="git-push-origin-master"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the push has finished, we can watch the progress of our Kotlin/JS application being built and prepared for publishing in the "Actions" tab of our GitHub repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fztnb7qdc5qpk4phezuqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fztnb7qdc5qpk4phezuqa.png" alt="action_running"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up GitHub Pages &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;After it finished, the workflow we created and triggered in the previous section put our final &lt;code&gt;.js&lt;/code&gt; and &lt;code&gt;.html&lt;/code&gt; artifacts on the &lt;code&gt;gh-pages&lt;/code&gt; branch of our repository, just as we planned:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr6lhyhlsxutuk9tux4oh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr6lhyhlsxutuk9tux4oh.png" alt="gh-pages-branch"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;It's time to &lt;strong&gt;enable the GitHub Pages feature&lt;/strong&gt; of our repository, and point it to this branch. We can do this using the "Settings" tab.&lt;/p&gt;

&lt;p&gt;Somewhere close to the bottom, we can find a section labelled "GitHub Pages". We select the &lt;code&gt;gh-pages&lt;/code&gt; branch and &lt;code&gt;/ (root)&lt;/code&gt; (default) and hit "Save":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F66pf58m8og9xrbnzg01z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F66pf58m8og9xrbnzg01z.png" alt="github-pages-enable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After saving our changes, scrolling back to this section reveals the &lt;strong&gt;URL under which our application is available&lt;/strong&gt;. (I have previously set up a custom domain for GitHub pages, so this one is used by default.) If you don't have a &lt;a href="https://docs.github.com/en/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site" rel="noopener noreferrer"&gt;custom configuration&lt;/a&gt;, the URL of your application usually takes the shape of &lt;code&gt;&amp;lt;username&amp;gt;.github.io/&amp;lt;reponame&amp;gt;&lt;/code&gt;. Visiting this URL shows our Kotlin/JS application in all its glory, and for the world to see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxr3ooqc9l4rgrpjia265.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxr3ooqc9l4rgrpjia265.png" alt="ready to be published"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;You can use this link to &lt;strong&gt;share your Kotlin/JS application&lt;/strong&gt; with friends and colleagues, or post it on your favorite news aggregator and wait for the upvotes to roll in! 😉&lt;/p&gt;

&lt;p&gt;(If your project is located in a private repository, you might want to change the GitHub Pages visibility. You can find more info on this in the &lt;a href="https://docs.github.com/en/github/working-with-github-pages/changing-the-visibility-of-your-github-pages-site" rel="noopener noreferrer"&gt;GitHub docs&lt;/a&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Take your project for a spin!
&lt;/h2&gt;

&lt;p&gt;We're done! From now on, whenever you push code, your project will automatically be built on GitHub's CI servers. If a commit is faulty, you can see so on the web interface – and you will even be reminded via email!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhvu8r28kptsqq99ys2rd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhvu8r28kptsqq99ys2rd.png" alt="checks failed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pushing to the main branch of the repository means your page (which is reachable at &lt;code&gt;&amp;lt;username&amp;gt;.github.io/&amp;lt;reponame&amp;gt;&lt;/code&gt;) will &lt;strong&gt;automatically&lt;/strong&gt; be updated.&lt;/p&gt;

&lt;p&gt;And when somebody makes a pull request, build and test status is also shown &lt;strong&gt;directly in context&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu3wl5tcsahepdma6pbbq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu3wl5tcsahepdma6pbbq.png" alt="pr failed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank you!
&lt;/h2&gt;

&lt;p&gt;I hope you found this post useful. &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt; is a &lt;strong&gt;powerful, but also complex tool&lt;/strong&gt;, and I hope that these instructions make it a bit easier to get started together with Kotlin/JS. You can find the &lt;a href="https://github.com/SebastianAigner/kotlin-js-on-gh-pages" rel="noopener noreferrer"&gt;sample project I used&lt;/a&gt; to create the screenshots for this tutorial on GitHub as well, and use it as a source of inspiration or template for a future project.&lt;/p&gt;

&lt;p&gt;If you're interested in similar content, consider &lt;strong&gt;giving me a follow&lt;/strong&gt;, here on dev.to or on Twitter &lt;a href="https://twitter.com/sebi_io" rel="noopener noreferrer"&gt;@sebi_io&lt;/a&gt; to stay up to date.&lt;/p&gt;

&lt;p&gt;If you have ideas for future tutorials, please &lt;strong&gt;share them&lt;/strong&gt; in the comments below, or anywhere else you can get a hold of me!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Special thanks to &lt;a href="https://twitter.com/hszanowski" rel="noopener noreferrer"&gt;Jakub Chrzanowski&lt;/a&gt; for sharing some of his CI wisdom with me for this blog post.&lt;/em&gt;!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>javascript</category>
      <category>github</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Kotlin Standard Library Safari: Strings</title>
      <dc:creator>Sebastian Aigner</dc:creator>
      <pubDate>Tue, 26 Jan 2021 12:12:30 +0000</pubDate>
      <link>https://dev.to/kotlin/kotlin-standard-library-safari-strings-3lj1</link>
      <guid>https://dev.to/kotlin/kotlin-standard-library-safari-strings-3lj1</guid>
      <description>&lt;p&gt;This blog post accompanies the first episode of our &lt;strong&gt;YouTube series&lt;/strong&gt; "Kotlin Standard Library Safari", which you can find on our &lt;a href="https://www.youtube.com/channel/UCP7uiEZIqci43m22KDl0sNw"&gt;official Kotlin YouTube channel&lt;/a&gt;, or watch here directly!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/n4WBip822A8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Kotlin Standard Library Safari?
&lt;/h2&gt;

&lt;p&gt;In the "Kotlin Standard Library Safari" series, we’re going  through the &lt;strong&gt;useful functionality&lt;/strong&gt; the standard library in Kotlin has to offer, one subject at a time. In the process, we’re hopefully going to unearth some &lt;strong&gt;hidden gems&lt;/strong&gt; together, which will come in handy the next time &lt;em&gt;you&lt;/em&gt; write Kotlin code. Because if you know how to wield it, the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/"&gt;Kotlin standard library&lt;/a&gt; is a &lt;strong&gt;powerful tool&lt;/strong&gt; which can help you be &lt;strong&gt;more productive solving your problems&lt;/strong&gt;, and be &lt;strong&gt;more expressive in your code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This episode is all about &lt;strong&gt;strings&lt;/strong&gt; – how we manipulate them, extract information, compare them, and much more. Let's get going!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating strings
&lt;/h2&gt;

&lt;p&gt;Strings are one of the most prevalent data types that you’re probably familiar with. After all, all kinds of information get stored in the form of text strings, one way or another. Probably even in your first ever Kotlin program, you had a &lt;strong&gt;&lt;a href="https://kotlinlang.org/docs/basic-types.html#string-literals"&gt;string literal&lt;/a&gt;&lt;/strong&gt; saying “Hello, World”, or something similar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Hello, World!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, as you may know, even &lt;a href="https://kotlinlang.org/docs/basic-types.html#string-literals"&gt;string literals&lt;/a&gt; can do a bit more in Kotlin than just statically storing some text.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;&lt;a href="https://kotlinlang.org/docs/basic-types.html#string-templates"&gt;string interpolation&lt;/a&gt;&lt;/strong&gt; (also called "string templates"), we can enrich our strings by referencing variables, calling functions, or even evaluating complex expressions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Johnathan"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, $name!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Hello, Johnathan&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Your name is ${name.count()} long!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your name is 9 long!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When our strings contain multiple lines of text or special characters that are usually reserved, like quotation marks or backslashes, we can use &lt;strong&gt;&lt;a href="https://kotlinlang.org/docs/basic-types.html#string-literals"&gt;multiline strings&lt;/a&gt;&lt;/strong&gt;, which are denoted by triple-quotes. Everything will still behave as expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
    Johnathan,
    The Great,
    The "Knowledgeable"
"""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trimIndent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, $name!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Your name is ${name.count()} long!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/* Prints:
Hello, Johnathan,
The Great,
The "Knowledgeable"!
Your name is 41 long!
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you type out these triple-quoted "raw" strings in &lt;a href="https://www.jetbrains.com/idea/"&gt;IntelliJ IDEA&lt;/a&gt;, you can notice that a call to &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/trim-indent.html"&gt;&lt;code&gt;trimIndent()&lt;/code&gt;&lt;/a&gt; is automatically added to the string. This function &lt;strong&gt;removes the &lt;em&gt;common&lt;/em&gt; indent of all input lines&lt;/strong&gt;, and also removes the first and the last lines if they are blank. This means that if we have some XML or JSON stored in a string, for example, we can keep its nice formatting without having to worry that we might introduce additional characters. Note how, in this example, the printed output is not indented, and doesn't begin or end with an unnecessary empty line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;myJson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
    {
      "name": "jane",
      "lastname": "doe",
      "age": 29
    }
    """&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trimIndent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myJson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Prints:
{
  "name": "jane",
  "lastname": "doe",
  "age": 29
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are worried about performance when invoking an extra function during string creation, fear not. For constant strings, this transformation is &lt;a href="https://blog.jetbrains.com/kotlin/2019/06/kotlin-1-3-40-released/#trimIndent"&gt;evaluated at compile time &lt;strong&gt;with no runtime overhead&lt;/strong&gt;&lt;/a&gt; since Kotlin 1.3.40.&lt;/p&gt;

&lt;p&gt;Of course, there are tons of other places where strings could come from. For example, Kotlin can &lt;strong&gt;read terminal input&lt;/strong&gt; via the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/read-line.html"&gt;&lt;code&gt;readLine()&lt;/code&gt;&lt;/a&gt; function. Or, we could &lt;strong&gt;read text from a file&lt;/strong&gt;, to name just two examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fromStdIn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readLine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fromFile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;readText&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another neat way of creating Kotlin strings yourself is via the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/build-string.html"&gt;&lt;code&gt;buildString&lt;/code&gt;&lt;/a&gt; function. We can give this function a code block which populates a &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-string-builder/"&gt;StringBuilder&lt;/a&gt;, which offers us functions like &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-string-builder/append.html"&gt;&lt;code&gt;append&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/append-line.html"&gt;&lt;code&gt;appendLine&lt;/code&gt;&lt;/a&gt;. This is particularly useful if you are &lt;strong&gt;crafting large strings&lt;/strong&gt;, and performance is a concern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Jane"&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;myString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildString&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;appendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/* Prints:
Hello, Jane!
Hello, Jane!
Hello, Jane!
Hello, Jane!
Hello, Jane!
Hello, Jane!
Hello, Jane!
Hello, Jane!
Hello, Jane!
Hello, Jane!
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there is a lot we can do with all these strings! Next to some functionality like upper- and lowercasing a string, Kotlin also comes with some functions that are particularly useful when we want to &lt;strong&gt;extract information&lt;/strong&gt; out of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extracting information from strings
&lt;/h2&gt;

&lt;p&gt;Extracting information usually means removing anything that isn’t useful. For example, we might want to detect strings that don’t contain any real information at all – so &lt;strong&gt;empty strings&lt;/strong&gt;, that have no characters in them, or &lt;strong&gt;blank strings&lt;/strong&gt;, that only contain whitespace.&lt;/p&gt;

&lt;p&gt;To check whether we have this kind of string, we can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/is-blank.html"&gt;&lt;code&gt;isBlank&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/is-empty.html"&gt;&lt;code&gt;isEmpty&lt;/code&gt;&lt;/a&gt; functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"   "&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isBlank&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also conveniently replace those empty and blank strings with &lt;strong&gt;default values&lt;/strong&gt; via the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/if-blank.html"&gt;&lt;code&gt;ifBlank&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/if-empty.html"&gt;&lt;code&gt;ifEmpty&lt;/code&gt;&lt;/a&gt; functions. Here, we can add a block which generates a default value for our strings if the corresponding condition is met:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;neverBlankString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ifBlank&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"Never blank!"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;neverBlankString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Never blank!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we have a string with meaningful content, but that information is surrounded by whitespace we can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/trim.html"&gt;&lt;code&gt;trim&lt;/code&gt;&lt;/a&gt; function to &lt;strong&gt;remove empty space&lt;/strong&gt; from the beginning and end of our string, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"    valuable info "&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// valuable info&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there are some other characters or maybe a common phrase which we don’t really care about on the sides of the text, there’s three more functions which are our allies: &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/remove-prefix.html"&gt;&lt;code&gt;removePrefix&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/remove-suffix.html"&gt;&lt;code&gt;removeSuffix&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/remove-surrounding.html"&gt;&lt;code&gt;removeSurrounding&lt;/code&gt;&lt;/a&gt;. With those, we can &lt;strong&gt;get rid of characters&lt;/strong&gt; in the front, the back, and enclosing the text respectively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"##placeholder##"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removePrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"##"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// placeholder##&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeSuffix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"##"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// ##placeholder&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeSurrounding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"##"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// placeholder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another big way of extracting information from strings is via &lt;strong&gt;&lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/"&gt;regular expressions&lt;/a&gt;&lt;/strong&gt;, or short regexes. But this is a bit of a bigger topic, so those will have to wait for a future episode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing strings
&lt;/h2&gt;

&lt;p&gt;Now that we know some tricks of how to get strings containing only the information we really care about, we can do things like compare those strings with each other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Equality checks&lt;/strong&gt; are easy enough, with the double-equals sign checking whether two strings are identical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;stringA&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"astring"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stringA&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"astring"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Everything cool!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Everything cool!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But did you know that you can also compare two strings based on their &lt;strong&gt;alphabetical order&lt;/strong&gt;? This can be done by using the less-than and greater-than signs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"c"&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In situations where we want to compare two strings &lt;strong&gt;regardless of how their text is capitalized&lt;/strong&gt;, we can use the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/compare-to.html"&gt;&lt;code&gt;compareTo&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/equals.html"&gt;&lt;code&gt;equals&lt;/code&gt;&lt;/a&gt; functions with the &lt;code&gt;ignoreCase&lt;/code&gt; parameter set to &lt;code&gt;true&lt;/code&gt;. Not only does this look nicer than calling &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/to-lower-case.html"&gt;&lt;code&gt;toLowerCase&lt;/code&gt;&lt;/a&gt; on both strings separately it also has better performance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"QuICK brOWN fox"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Quick Brown Fox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ignoreCase&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Turning strings into collections
&lt;/h2&gt;

&lt;p&gt;But often strings also contain multiple pieces of information which we would like to work with individually. To &lt;strong&gt;rip apart a string&lt;/strong&gt; into pieces, there’s a number of options.&lt;/p&gt;

&lt;p&gt;Most generally, the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/split.html"&gt;&lt;code&gt;split&lt;/code&gt;&lt;/a&gt; function is our friend here: we can specify a character, word or other string which will be used as a splitter, and the function gives us a nice list of the &lt;strong&gt;individual string pieces cut up by our delimiter&lt;/strong&gt;. Consider, for example, the following &lt;code&gt;input&lt;/code&gt; string, which contains 5 letters, all separated by &lt;code&gt;;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"A; B; C; D; E"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"; "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// A, B, C, D, E&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is a list with five elements.&lt;/p&gt;

&lt;p&gt;And if we only want to make a &lt;strong&gt;limited number of cuts&lt;/strong&gt;, we could also pass a &lt;code&gt;limit&lt;/code&gt; to the split function. And then we’ll only get three pieces of text as a result, for example, with the last piece being the remainder of the string which wasn’t split any further. Let's consider the previous example once more, this time with a limit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"A; B; C; D; E"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"; "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// A, B, C; D; E&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is a list with three elements: &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, and &lt;code&gt;C; D; E&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the special case of &lt;strong&gt;splitting a string up by lines&lt;/strong&gt;, there’s the very accurately named &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/lines.html"&gt;&lt;code&gt;lines&lt;/code&gt;&lt;/a&gt; function which, as you may have guessed, gives you back your text line-by-line. The nice part here is that we don’t have to remember what the escape sequence for newlines are. Was it &lt;code&gt;\n&lt;/code&gt;? &lt;code&gt;\r\n&lt;/code&gt;? Who cares, we have the lines function!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
    Well this is crazy
    I'm a multiline string
    So split me maybe?
"""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trimIndent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;// [Well this is crazy, I'm a multiline string, So split me maybe?]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And of course, we can do all sorts of fancy things once we have a collection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treating strings as collections of characters
&lt;/h2&gt;

&lt;p&gt;And, to be exact, even an individual string behaves like a collection – since it's a &lt;strong&gt;collection of characters&lt;/strong&gt;! On the one hand, this means that we can use the array operator to pick out characters at specific indexes, which can prove quite useful. But it also means that stuff like &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map.html"&gt;&lt;code&gt;map&lt;/code&gt;ping&lt;/a&gt;, &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter.html"&gt;&lt;code&gt;filter&lt;/code&gt;ing&lt;/a&gt;, and friends all work directly on strings as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello, World"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// e&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// HW&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will tackle those &lt;strong&gt;collection operations&lt;/strong&gt; in a future episode of "Kotlin Standard Library Safari" – so, if you don’t want to miss me exploring those in the future, make sure to &lt;a href="https://dev.to/kotlin"&gt;&lt;strong&gt;follow&lt;/strong&gt; @kotlin here on dev.to&lt;/a&gt;, and &lt;strong&gt;subscribe&lt;/strong&gt; to &lt;a href="https://www.youtube.com/channel/UCP7uiEZIqci43m22KDl0sNw"&gt;our official YouTube channel&lt;/a&gt; to get updates on when a new episode is available!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's all for this first segment on the Kotlin standard library. I hope that you enjoyed this brief overview of &lt;em&gt;things to do with strings&lt;/em&gt; in Kotlin. There is, of course, still more stuff you can do. A great starting point for your &lt;strong&gt;own exploration&lt;/strong&gt; of the string APIs available is the &lt;a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/"&gt;documentation on text&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;If you know of some tips you'd like to see featured in a future episode, make sure to &lt;strong&gt;share them on Twitter&lt;/strong&gt; and tag &lt;a href="https://twitter.com/sebi_io"&gt;@sebi_io&lt;/a&gt; and &lt;a href="https://twitter.com/kotlin"&gt;@kotlin&lt;/a&gt; – and maybe we'll see your tip in a future part of this series!&lt;/p&gt;

&lt;p&gt;I hope you learned something new, and that you will go and explore some more Kotlin!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>programming</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
