# Topics

• Type inference
• Arrays
• Characters and strings
• Escape sequences
• Raw strings
• String templates (or string interpolations)
• String functions
• Scanner
• the format() function

# Type inference

• We have been declaring the type of every variable at the same time that we define it. It turns out for almost all the time we can omit type declaration.
• For example, instead of writing val n: Int = 3, we can simply write

val n = 3
• The Kotlin compiler has a builtin algorithm called type inference engine that can infer the type of the variable being declared from the type of the expression used to initialize it.
• You can still declare the type of a variable explicitly. In that case the compiler checks that the declared type agrees with the type of the initializing expresssion, and gives an error message if they don’t.

# Arrays

• Arrays is an aggregate type. An array is made up of pieces of data of the same type called elements. The type of elements is called the base type. If B is a base type, the type “array of B” is written in Kotlin as Array<B>.
• For example, we can have Array<String>, Array<Array<Int>>, etc. Thus, array types allow us to construct an infinite number of new types.
• If an array has $$n$$ elements, the elements are indexed using the nonnegative integers from $$0$$ to $$n-1$$.
• We can access and modify an individual element through its index using the [] notation, e.g., a[3] is the element of a at index 3.
• The (references to) array elements are located at consecutive memory locations.
• The reason arrays is an efficient data structure for keeping bunches of things together is because we can get at each individual element quickly by doing arithmetic on its index.

# Arrays of primitive types

• Arrays of primitive types are efficient running-time-wise and memory-wise. You should try to use it if you care about efficiency.
• The names of arrays of primitive types are
• BooleanArray
• CharArray
• ByteArray
• ShortArray
• IntArray
• LongArray
• FloatArray
• DoubleArray

# Constructing primitive arrays

• Kotlin does not provide a way to write array literals. The only way to create a new array is by calling some special function. Here are example declarations of arrays of primitive types:

val a1 = IntArray(5)
val a2 = intArrayOf(3, 5, 2)
• The first statement declares the variable a1 to be an IntArray, creates an array of 5 Ints, initializes all elements to zero, then makes a1 point to the beginning of this array.
• The second statement declares the variable a2 to be an IntArray, creates an array of 3 elements, initializes the 0th element to 3, the 1st element to 5, and the 2nd element to 2, then makes a2 point to the beginning of this array.
• You will learn later that IntArray(5) is calling an array constructor while intArrayOf(3, 5, 2) is calling a factory function.

# Constructing primitive arrays, continued

• In a similar manner, you have constructors
• BooleanArray(n) for constructing a BooleanArray of size n and initializing all elements to false
• ByteArray(n) for constructing a ByteArray of size n and initializing all elements to 0
• ShortArray(n) for constructing a ShortArray of size n and initializing all elements to 0
• LongArray(n) for constructing a LongArray of size n and initializing all elements to 0
• FloatArray(n) for constructing a FloatArray of size n and initializing all elements to 0.0
• DoubleArray(n) for constructing a DoubleArray of size n and initializing all elements to 0.0
• You also have factory functions booleanArrayOf(...), byteArrayOf(...), shortArrayOf(...), longArrayOf(...), floatArrayOf(...), and doubleArrayOf(...) for creating and initializing arrays of the other primitive types to the values you provide as arguments.

# Reading and modifying array elements

• Here is an example of performing various operations on arrays.

val a = intArrayOf(0, 1, 2, 3, 4)
println("originally a = ${a.joinToString()}") for (i in 0 until a.size) a[i] *= a[i] println("after the for loop, a is now =${a.joinToString()}")
val b = a
println("originally b = ${b.joinToString()}") b[0] = b[2] - b[1] println("after modifying b[0], b =${b.joinToString()}")
println("and a = ${a.joinToString()}") • Executing the code gives this output originally a = 0, 1, 2, 3, 4 after the for loop, a is now = 0, 1, 4, 9, 16 originally b = 0, 1, 4, 9, 16 after modifying b[0], b = 3, 1, 4, 9, 16 and a = 3, 1, 4, 9, 16 # Arrays is a mutable, reference type • A data object that allows changes to be made to its value is said to be mutable. (To mutate means to change.) A data object that does not allow changes to be made to its value is said to be immutable. The last piece of code snippet taught us that arrays are mutable. • Except for primitive types, all Kotlin types are reference types. The data itself is kept within an object, and the variable only keeps a reference to the location of the object. Objects are created during runtime. • When we execute the code snippet val b = a where a, b are variables of the same reference type, the variable b is made to point to the same object that a is pointing to. Modifying the content that b points to will change the content that a points to as well since they are the same! • The lesson here is that being a val variable does not mean the data itself is immutable. It just means that you can’t change that variable to make it reference something else. # Iterating an array • Arrays are iterable, so you can use the for loop to walk through them to perform some task on their elements without having to refer to their indexes at all. • For example, you can print all the elements by val a = intArrayOf(1, 2, 3) for (e in a) println(e) • If you also want the indexes, you can write for ((i, e) in a.withIndex()) println("$i: $e") instead of the usual for (i in 0 until a.size) println("$i: ${a[i]}") # Characters and strings • A String value is essentially a sequence of Char values. • Even though String is not a primitive type, it is so heavily used that Kotlin provides literals for it like for the primitive types. It also has the concatenation operator + that returns another string that results from appending the second string to the first. • String is an immutable type. You can’t change its data. • But you can access the individual characters of a string using the indexing operator [], exactly like the arrays. • The String type differs from the array type in that strings don’t have a size property; it has a length property instead. • You can iterate through strings just like arrays. # Strings, continued • Here is some code that manipulates strings. val message = "Hello" println(message + " World") println(message.length) for (c in message) println(c) for (i in 0 until message.length) println(message[i]) for ((i, c) in message.withIndex()) println("$i: ${message[i]}") • Strings can be compared using these operators as well: == != < <= > >= in !in Comparison is done in dictionary order. # Escape sequences • The Char data represents 16-bit Unicode characters. The Unicode characters are supposed to represent all the symbols used in all languages in the world, whether the language is alphabet-based or not, and then some. However, some Unicode characters are either not printable or not easy to see when printed; Kotlin provides a special notation called escape sequences for writing these characters. • These are the escape sequences and their meanings: Escape Sequence Represented Character \t Tab \b Backspace \n Newline \r Carriage Return \' Single Quotation Mark \" Double Quotation Mark \\ Backslash \$            Dollar sign
• You can also write any Unicode character using the escape sequence syntax like ‘\uFF00’.

# Raw strings

• A regular Kotlin string literal can contain escape sequences. However, literals containing many escaped characters can be hard to read, so Kotlin provides another way to write string literals.
• A raw string does not understand escape sequences. Instead of using just one quotation mark " to enclose a string, a raw string uses three quotation marks """ like this:

  """Roses are red,
Violets are blue,
sugar is sweet,
And so are you."""

# Raw strings, continued

• If you try to print out the raw string in the last slide you’ll find it has undesirable blanks at the beginning of the last 3 lines. To eliminate them, Kotlin provides a function trimMargin() so we can write the above raw string as

"""
|Roses are red,
|Violets are blue,
|sugar is sweet,
|And so are you.
""".trimMargin()
• The default margin prefix is the | character but you can provide your own and pass it in as argument to trimMargin() like this:

"""
>Roses are red,
>Violets are blue,
>sugar is sweet,
>And so are you.
""".trimMargin(">")

# String templates (or string interpolations)

• We have used string templates already. The simplest string template starts with the $character, followed by a variable name. Instead of variable name, we can also put an arbitrary expression enclosed in braces. • A string template tells Kotlin to construct a new string by replacing the$ character and the ensuing variable name or brace-enclosed expression with its value (after converting it to a string if necessary).
• For example,

val name = "John"
val age = 20
println("Last year $name was${age-1} years old.")

will print

Last year John was 19 years old.

# Fine points

• The escape sequences can be used both within character literals and regular (non raw) string literals. Escape sequences do not work within raw strings but we can write the newline character directly within it. Therefore, the two string variables s1 and s2 below have the same content.

    val s1 = "One\nTwo\n\Three"
val s2 = """One
Two
Three"""
• Both regular string literals and raw strings understand string templates.
• To get the dollar sign into regular string literals, we can escape it with a backslash like this “\$100”. • However, raw strings don’t treat backslash in a special way, so there must be some other way to specify the dollar sign within raw strings. We can do it this way """That item costs${'\$'}20."""

# String functions

• There are lots of string functions that you will find helpful in your programming. We list some of them here.

indexOf(                            contains(s: CharSequence): Boolean
char: Char,                     compareTo(other: String,
startIndex: Int = 0,                ignoreCase: Boolean = false): Int
ignoreCase: Boolean = false     startsWith(prefix: String): Boolean
): Int                              endsWith(suffix: String): Boolean
isBlank(): Boolean                  replace(
isNotBlank(): Boolean                   oldChar: Char,
isEmpty(): Boolean                      newChar: Char
isNotEmpty(): Boolean               ): String
last(): Char                        replace(
lastIndexOf(                            target: CharSequence,
char: Char,                         replacement: CharSequence
startIndex: Int = lastIndex,    ): String
ignoreCase: Boolean = false     toLowerCase(): String
): Int                              toUpperCase(): String
repeat(n: Int): String              toBoolean(): Boolean
reversed(): String                  toByte(): Byte
substring(startIndex: Int): String  toShort(): Short
substring(                          toInt(): Int
startIndex: Int,                toLong(): Long
endIndex: Int                   ...
): String                           trim(): String

# Scanner

• A Scanner is a class that allows you to parse many kinds of numeric and string literals in a text stream. It is appropriate when the exact format of input is known beforehand so you can tell it to read in and parse the right kind of literals at the right time.
• The source code for the Scanner class is written in the Java programming language. Since Kotlin-JVM is 100% interoperable with Java, you can call any Java library function from Kotlin. Scanner is no exception.
• A concept used by the Scanner is that of whitespace. This term refers to the characters blank (' '), tab (‘\t’), and newline (‘\n’), and some others. Another concept is that of a cursor. Every Scanner object is equipped with a cursor. It starts scanning the stream by setting the cursor to the beginning of the stream.
• As you tell the scanner to scan the next input token, it will move the cursor past any whitespace character until it encounters the first non-whitespace character. It will then try to read in as much of the input as possible that can be part of a token for the type of input it is parsing. It leaves the cursor at the first character that cannot be part of a valid token for that type of input.

# Scanner, continued

• Let’s look at an example of how to scan the standard input. Suppose our input consists of a sequence of lines that look like this:

Albania 2.99    11100
Belgium 10.43   11787
Cuba    11.09   42803
Denmark 5.53    16639
• Each line consists of three whitespace-separated pieces of data: country, population in millions, and area in square miles. Assume for simplicity that the name of a country is one word, population is a number with a decimal point, and area is a whole number.
• We can use the scanner to parse the data like this.

val scanner = java.util.Scanner(System.in)
while (scanner.hasNext()) {
val country = scanner.next()
val population = scanner.nextDouble()
val area = scanner.nextInt()
// process data for this country here
}

# Useful Scanner functions

• Here is a list of some useful Scanner functions:

hasNext()           next()
hasNextLine()       nextLine()
hasNextBoolean()    nextBoolean()
hasNextByte()       nextByte()
hasNextShort()      nextShort()
hasNextInt()        nextInt()
hasNextLong()       nextLong()
hasNextFloat()      nextFloat()
hasNextDouble()     nextDouble()

# Formatted output

• Imagine you have a piece of datum of primitive or string type. You may want to output it in various ways to make the output look nice. You can do that using the String.format function.
• Let’s first learn the concept of a format specifier. It’s a string consisting of one required part and three optional parts

"[flags][width][.precision]type"

Only type is required.

# Formatted output, continued

• This table shows most of the possible types and their meanings.

type specifier meaning
%b Boolean
%c Char
%d integral type
%e floating point type in scientific notation
%f floating point type in decimal format
%g floating point type in either decimal or scientific notation, depending on value
%n line separator
%s string
%x integer in hex
%% The % symbol itself

# Formatted output, continued

• This table shows examples of format specifiers and their effect on the output string.

type code typical literal sample format strings converted string values for output
Int d 512 “%14d” “              512”
Long d 512L “-14d” “512              ”
Float f 1595.1680010754388F “14.2f” “        1595.17”
Double f 1595.1680010754388 “.7f” “1595.1680011”
Double e 1595.1680010754388 “14.4e” “    15952e+03”
String s “Hello, world” “14s” “  Hello, world”
String s “Hello, world” “-14s” “Hello, world  ”
String s “Hello, world” “-14.5s” “Hello             ”

# Formatted output, continued

• format is a String function. You call it using the . operator on the string whose content is the format specifier, and provide it with as many arguments as specified in the specifier. Examples:

"%s %d pounds.".format("The baby weighs", 3)

gives the string

"The baby weighs 3 pounds."