# Topics

• Types: primitive, basic, reference
• Literals
• Operators
• Keywords & identifiers
• Variables & assignment
• Expressions
• Function calls
• kotlin.math package
• Processing command line arguments
• Generating random numbers

# Types

• A type is a set of values together with its associated operations. Every piece of Kotlin datum has a type.
• Kotlin is a statically-typed language, i.e., the type of a variable is determined at compile time. This is in contrast to dynamically-typed language, e.g., Python that determines the type of a piece of datum at run time, i.e., while the program is running.
• Kotlin is an object-oriented language in the sense that it gives the user the illusion that every value is an object.
• However, values of the following basic types have special implementation, making it take less space and execute faster: Boolean, Char, Byte, Short, Int, Long, Float, Double. We’ll call these the primitive types.
• String and Array are basic types but not primitive.
• There are a lot more types than the basic types; we’ll study them later.

# Primitive types

• The primitive types represent values and operations that exist in most programming languages.
• There are four main groups: boolean, character, integer, and floating-point.
• There’s only one type in the boolean group, namely Boolean. There are only two possible values of this type: true and false.
• There’s only one type in the character group, namely Char. A value of this type takes up two bytes of storage and represents a 16-bit Unicode character.
• There are four types in the integer group, namely Byte, Short, Int, and Long. A Byte value takes up one byte of storage; a Short value takes up two bytes of storage; an Int value takes up four bytes of storage; and a Long value takes up eight bytes of storage.
• There are two types in the floating-point group, namely Float and Double. A Float value takes up four bytes of storage, while a Double value takes up eight bytes of storage.

# Primitive VS reference types

• Besides the primitive types, Kotlin also has non-primitive types called reference types.
• A value of reference type is accessed through its reference (a kind of pointer) but a value of primitive type can be accessed directly without going through this kind of indirection.
• The JVM also has special instructions for performing various operations on values of primitive types.
• A value of reference type is an object. Associated with every object are properties that a user may inspect and/or modify, and functions that a user can invoke. Therefore, an object takes up space for its properties and functions.
• Kotlin primitive types are therefore more efficient than reference types for all the above reasons.

# Primitives and their wrapper types

• In fact, every Kotlin value of primitive type has a corresponding object version of reference type, called its wrapper type!
• Some operations (like the arithmetic operations) can operate on the primitive values, while others (like inspecting properties and function invocations) needs an object to operate on.
• The Kotlin compiler takes care of switching between values of primitive types and their corresponding wrapper types behind the scene as needed!
• As a result, the user can regard all values as objects and does not have to be aware of the existence of primitive types, reference types, the differences between them, or wrapper types. However, as a computer scientist using the language, you should know about these things so you can write efficient code.

# Literals, integer literals

• A literal is a source code level representation of data value.
• An integer literal may be written in 3 different bases: two, ten, and sixteen. Here are the different ways to write the number twelve.
• in binary (base-two): 0b1100
• in decimal (base-ten): 12
• in hexadecimal (base-sixteen): 0xC
• There are two kinds of type that an integer literal have, either Int or Long. Kotlin chooses the smallest type that can contain the value. It is an error if the intended integer value of what your write is too large to fit in a Long. Examples:

>>> 12345678232323291110
error: the value is out of range
12345678232323291110
^

>>> 1234567890
res1: kotlin.Int = 1234567890
>>> 1234567823232329111
res2: kotlin.Long = 1234567823232329111

# Integer literals, continued

• An Int literal can be assigned to a Byte or Short variable without getting a compile-time error if the value is within range. Examples:

>>> val a: Byte = 256
error: the integer literal does not conform to the expected type Byte
val a: Byte = 256
^

>>> val a: Byte = -128
>>> a
res1: kotlin.Byte = -128
• An integer literal can be forced to have type Long by appending the suffix L, e.g., -1L has a Long type.

>>> val a = -1L
>>> a
res0: kotlin.Long = -1

# Floating-point literals

• A floating-point literal can be written in 2 different ways
• like how we write real numbers in mathematics: 3.134
• in scientific notation: 2.1e10, 3e-7
• The type of all floating-point literals is Double by default.
• To get a Float literal, add a suffix ‘f’ or ‘F’. E.g. 3.14F has a Float type.
• One cannot write an overflowing floating-point literal because any floating-point literal that overflows becomes Infinity or -Infinity. Also, floating-point numbers cannot be represented precisely. Examples:

>>> 1.2e1111
res0: kotlin.Double = Infinity
>>> -1.2e1111
res1: kotlin.Double = -Infinity
>>> 1.2e-1111
res2: kotlin.Double = 0.0

# Char literals

• A character literal is written by quoting its content in a pair of single quotation mark.
• Most printable characters can be written directly inside the quotes. Examples are ‘a’, ‘%’, and ‘ ’.
• Some printable characters cannot be written directly because they have special meaning. For example, the backslash character is used to create what’s called an escape sequence (to be described momentarily), so you have to write it as ‘\\’. Similarly, the single quotation mark is used to delimit character literals, so needs to be escaped as well; it is written as ‘\’’
• Some characters are not printable, but we can still write a literal for such a character using an escape sequence.
• An escape sequence starts with the backslash character, followed by one of
• a single character (b, t, n, r, “, ’, $, or \) • an octal number between 000 and 377 • a u followed by four hex digits specifying a unicode character. # Char literals, continued • Example escape sequences: Escape Sequence Unicode Meaning ‘\b’ ‘\u0008’ backspace ‘\t’ ‘\u0009’ horizontal tab ‘\n’ ‘\u000a’ linefeed ‘\r’ ‘\u000d’ carriage return ‘\"’ ‘\u0022’ double quotation mark ‘\'’ ‘\u0027’ single quotation mark ‘\$’ ‘\u0024’ dollar sign
‘\\’ ‘\u005c’ backslash

# String literals

• A string literal is any sequence of characters enclosed in a pair of double quotation marks.
• Example string literals are
• “Hello”
• “Good Bye!”
• “123456”
• “true”
• “false”
• “Int”
• “print()”
• We will explore string literals in detail later.

# Operators

• The are several groups, taking operands of different types. Here is a selection of some operators:
• arithmetic:   +   $$-$$   *   /   %
• logical:   &&   ||   !
• comparison:   <   <=   >=   >
• equality:   ==   !=
• bit-wise:   shl   shr   ushr   and   or   xor   inv
• increment & decrement:   ++   $$-$$$$-$$
• assignment:   =   +=   $$-$$=   *=   /=   %=
• miscellaneous:   +   $$-$$   .   []   ()   in   !in   is   !is
• Some operators are overloaded. Therefore, it’s important to know what each operator means in all possible contexts. Examples of overloaded operators are +   $$-$$   *   /   %

# Operator Precedence

• An expression like 2+3*4 is actually ambiguous, i.e., it has more than one possible interpretation, and thus meaning. In one interpretation the + is done before *; In the other interpretation the + is done after *.
• The term operator precedence denotes the degree of tightness of binding of operators to operand(s).
• Each operator has a precedence level.
• In an ambiguous expression, operator precedence is used to determine which operation to perform first.
• For example, *, /, and % are at the same precedence level. Also, + and $$-$$ are at the same level. However, the precedence level of *, /, and % is higher than that of + and $$-$$.
• Therefore, in the expression 2+3*4, multiplication is performed before addition since the * operator has higher precedence than +.

# Operator Associativity

• When an expression involves at least two operators of the same precedence level applied successively, Kotlin uses associativity of operators to determine whether to associate the middle operand with the left operator (left-associative) or the right operator (right-associative).
• For example, the expression 1-3-4 will be parsed by the Kotlin compiler as if we had written (1-3)-4 due to the fact that the minus operator is left-associative.
• Most operators in Kotlin are left-associative. Examples of right-associative operators are the unaryPlus + and unaryMinus $$-$$ operators.
• Notes.
• We can use parentheses to overide the precedence and associativity rules if desired.
• When in doubt, parenthesize the expression to make your intention clear.

# Basic Types

Type Size in Bits Sample Operators Literals
Boolean unspecified &&   ||   ! true   false
Byte 8 +   $$-$$   *   /   %
Char 16 + ‘a’   ‘0’   ‘\\’
Short 16 +   $$-$$   *   /   %
Int 32 +   $$-$$   *   /   % 321   0x3A   0b11
Long 64 +   $$-$$   *   /   % 3L
Float 32 +   $$-$$   *   /   % 2F   14.2e23f
Double 64 +   $$-$$   *   /   % 3.21   14.2e23
String + “Hello”
Array []

# String Type

• Strings have some features of basic types.
• We can write a string value using literals, e.g., “Hello”
• Strings can be concatenated with the operator +, e.g.,
• “This is an example” + " string" ⇒ “This is an example string”
• “The value is ” + 13 ⇒ “The value is 13”
• We will study strings in more detail later.

# Keywords

• Keywords are the reserved words of Kotlin. Their meanings are pre-defined and fixed. You cannot use a keyword to mean something else, unless you quote them in backticks, like this: in.
• Here is a list of the hard keywords

as as? break class continue do else false for fun
if in !in interface is !is null object package return
super this throw true try typealias val var when while
• There are other kinds of keywords. We may encounter some of them later.

# Identifiers

• Kotlin is a case-sensitive language; it distinguishes the uppercase from the lowercase letters.
• An identifier is a programmer-invented name to denote program constructs like variable, class, interface, function, etc.
• Syntactically, an identifier is a sequence of letters, digits, or underscore character such that its first character is not a digit. An identifier cannot be a keyword.
• Convention for writing an identifier:
• the camel hump style is recommended, e.g., ticketNumber
• variable name starts with a lowercase letter
• class name starts with a uppercase letter, e.g., BigInteger
• constants & enumerated literals are in all caps, e.g., MAX_LINE_LENGTH

# Variables and assignment

• A variable is a name associated with memory location whose value is changeable via an assignment statement.
• A variable has many attributes, e.g., memory location, name, type, value, scope, life time.
• An assignment statement starts with name of the variable, followed by the = operator, followed by an expression. E.g.

a = 2 * b + 6
• For simplicity, assume the variable has primitive type. Then the assignment statement means to evaluate the expression on the right-hand-side (RHS) of =, then put its value in memory location of the variable on the left-hand-side (LHS).
• Thus, the variable name appearing on the LHS denotes memory location while any variable name appearing on the RHS denotes value.

# Variables, continued

• There are two kinds of variables, the readonly kind, and the read-write kind.
• A better name for readonly variable is “assign-once” variable. A better name for read-write variable is “assignable-multiple-times” variable.
• Both kinds must be declared before use.
• You should preferentially use the readonly kind of variables whenever possible. Use the read-write kind only when necessary.

• The readonly variables are declared using the keyword val.
• They must be initialized with some value (using the assignment syntax) exactly once in a program.
• After initialization, the value of a readonly variable is fixed. You are not allowed to assign a value to it again.
• Example declaration and usage:

val c : Char = 'A'
val digit : Char = '9'
val greeting : String = "Hi"
val person : String = "Alice"
println(greeting + " " + person)

• A read-write variable is declared with the keyword var.
• It can be assigned values many times during the execution of a program.
• Example declaration, usage, and reassignment:

var n : Int = 1
var f : Float = 0F
var d : Double = 2.1
f = f * 3.1F
d = 3e-2
var greet : String = "Hello!"
greet = "Hi"

# Expressions

• The simplest kind of expression consists of literals, variables, and function calls joined together by operators.

b * 2 / 3 + kotlin.math.sin(4.0)
• Every expression has a type and value.
• There are other kinds of expressions. We’ll come to them soon.

# Type conversion

• In an arithmetic expression involving mixed types of numeric operands, Kotlin has overloaded the operators so it seems as if to convert the values in the following direction to make both operands have the same type as the “biggest” type.

Byte → Short → Int → Long → Float → Double
• Examples:

3 + 4.2        // value: 7.2, type: Double
1 + 7L - 2     // value: 6L,  type: Long
• The user can also explicitly requests the compiler to convert a value of one type into another type. E.g.

val a : Int = 2
val b : Byte = (a + 3).toByte()
val s : Short = 4.toShort()

# Function calls

• These type conversion functions are associated with objects. You call them using the . operator.
• toBoolean()
• toChar()
• toByte()
• toShort()
• toInt()
• toLong()
• toFloat()
• toDouble()
• Example usage:

"TrUe".toBoolean() ⇒ true
66.toChar() ⇒ 'B'
25.toByte() ⇒ a Byte type with value of twenty-five
265.toByte() ⇒ a Byte type with value of nine

# Input/Output Functions

• These are the output functions you can use. All of them output their argument(s) to the standard output.
• print() — outputs its argument.
• println() — outputs its argument and a newline, and flushes the output buffer.
• Both the print() and println() functions take exactly one argument. Their argument can be of any type, and it is automatically converted to the String type (if necessary) before being output.

# The ‘kotlin.math’ package

• There is a kotlin package that provides many useful mathematical functions and constants. Here is a partial selection of what’s available.
• abs — for Double, Float, Int, and Long
• min, max — for Double, Float, Int, and Long
• floor, ceil, round, truncate — for Double and Float
• sin, cos, tan — for Double and Float
• exp, ln, log10, log2, log — for Double and Float
• pow — for Double and Float
• sqrt — for Double and Float
• roundToInt, roundToLong — for Double and Float
• E — the famous $$e$$ (the base of natural logarithm)
• PI$$\pi$$ (the circle constant: circumference $$\div$$ diameter)
• See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.math/index.html for all possibilities.

# Processing command line arguments

• When a java class starts running, it also receives command line arguments as an array of strings. For example, when you type

$java MyClass zero ein deux MyClass gets its zeroth argument args[0] as the string “zero”, its first argument args[1] as the string “ein”, and its second argument args[2] as the string “deux”. • By checking these command line arguments, your program can make sure the user provides reasonable arguments before starting to execute. If any provided argument is not reasonable, the program can print an error/help message and abort. • To abort a program, you call the exitProcess() function. This function takes an integer argument and returns that value to denote the success or failure result of running the program. • The exitProcess() function belongs to the kotlin.system package, which is not automatically loaded in by default. Therefore, you should include the line import kotlin.system.exitProcess at the top of your source file that makes any call(s) to exitProcess(). • Another way to do error checking is to use the try {...} catch {...} statement. This involves exception, a concept we’ll study later. # Generating random numbers • An essential routine heavily used in computer simulation is random number generation. • The sequence of numbers generated by a computer as random numbers are in fact predictable. However, they have properties common with random numbers and are usually good enough for use. The name we use for these numbers is pseudo-random numbers. • Kotlin provides pseudo-random number generators in the kotlin.random package. To use this package, you include the line import kotlin.random.* at the top of your source file. • You call a function to generate a random number through the Random object. These functions include nextBoolean(), nextInt(), nextLong(), nextFloat(), nextDouble(). # Example program /* * This program demonstrates how to process command line arguments, and shows * how to call some random number generating functions. * See * * https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.random/-random/index.html * * for all possibilities. */ import kotlin.system.exitProcess import kotlin.random.* fun main(args: Array<String>) { val lo : Int val hi : Int if (args.size != 2) { println("Please give me exactly two nonnegative integers as arguments.") exitProcess(1) } try { lo = args[0].toInt() } catch (e: NumberFormatException) { println("'${args[0]}' is not an integer.")
exitProcess(2)
}
try {
hi = args[1].toInt()
}
catch (e: NumberFormatException) {
println("'${args[1]}' is not an integer.") exitProcess(2) } if (lo < 0 || lo > hi) { println("Please give me 2 nonnegative integers lo and hi, with lo <= hi.") exitProcess(3) } // a pseudo-random integer var k = Random.nextInt() println("Your random integer is:$k")

// a pseudo-random integer between 0 and hi-1
k = Random.nextInt(hi)
println("Your random integer between 0 and ${hi-1} inclusive is:$k")

// a pseudo-random integer between lo and hi
k = Random.nextInt(lo..hi)
println("Your random integer between $lo and$hi inclusive is: $k") // a pseudo-random real between 0.0 and 1.0 val r = Random.nextDouble() println("Your random real number in [0, 1) is:$r")
}