- Pairs & Triples
- Lists
- immutable
- mutable

Kotlin does not have a tuple type like Python, but it has pairs and triples.

`>>> var p = Pair(2, 3.5) >>> p = Pair(1, 2) error: type inference failed. Expected type mismatch: inferred type is Pair<Int, Int> but Pair<Int, Double> was expected p = Pair(1, 2) ^ >>> p = Pair(1, 2.0)`

The components of a pair or triple can be accessed as the properties

`first`

,`second`

, and`third`

.`>>> p.first 1 >>> p.second 2.0`

- Note that pairs and triples are “generic types”, e.g.,
`Pair(1, 2.0)`

is of type`Pair<Int, Double>`

. The “type parameters” are written comma-separated inside angle brackets. Type parameters indicate the components' types. - You can also write
`Pair(a, b)`

using infix notation as`a to b`

. Kotlin implements pairs and triples as data classes. Thus, they come equipped with a nice

`toString()`

method, and the`==`

and`!=`

operators work on them in the expected way,`>>> val p1 = Pair(1, 2.3) >>> val p2 = 1 to 2.30 >>> p1 == p2 true >>> p1 != p2 false >>> p1 (1, 2.3)`

When declaring variables, you can “destructure” a pair or triple like in Python:

`>>> val (n, d) = p >>> n 1 >>> d 2.0`

The

*destructuring declaration*`val (n, d) = p`

declares two variables and give them values at once. It’s equivalent to writing`>>> val n = p.first >>> val d = p.second`

Pairs and triples are useful for returning more than one value from a function, and destructuring allows one to concisely declare multiple variables to capture the return values of a function.

- A
`List`

is a generic type containing objects of the same type arranged in a linear sequence that can be accessed through a nonnegative index. For any type “T”,`List<T>`

is an immutable list of elements of type T. E.g.,

`>>> val students = listOf("Alice", "Bob", "Charlie", "David") >>> students [Alice, Bob, Charlie, David] >>> students.size 4 >>> students[0] Alice >>> students[3] David`

The type of

`students`

is`List<String>`

—every list element has type`String`

. It contains`students.size`

elements that can be indexed as`students[i]`

for all indices from`0`

to`students.lastIndex`

, that is,`L.lastIndex == students.size - 1`

holds.

You can iterate over a list using this

`for`

-loop construct:`>>> for (s in students) ... println(s) Alice Bob Charlie David`

If you need to know the indices of elements while iterating over the list, you can write

`>>> for (i in students.indices) ... println("$i: ${students[i]}") 0: Alice 1: Bob 2: Charlie 3: David`

- Some useful properties and functions of every list
`L`

follow.`L.size`

gives the length of the list;`L.lastIndex`

is the greatest valid index; it equals`L.size-1`

;`L.first()`

gives the initial element of the sequence;`L.last()`

gives the final element of the sequence;`L.isEmpty()`

is`true`

iff`L.size == 0`

;`L.isNotEmpty()`

is`true`

iff`L.size != 0`

;`e in L`

(or`L contains e`

) is`true`

iff`L`

contains an element equal to`e`

;`L.take(n)`

returns a new list containing the first \(n\) elements of`L`

;`L.drop(n)`

returns a new list containing all elements of`L`

except the first \(n\);`L.takeLast(n)`

returns a new list containing the last \(n\) elements of`L`

;`L.dropLast(n)`

returns a new list containing all elements of`L`

except the last \(n\);

- More useful functions of every lists
`L`

,`L1`

and`L2`

follow.`L.max()`

,`L.min()`

,`L.sum()`

, and`L.average()`

returns the largest, smallest, sum, and average of the elements of the numeric list`L`

;`L.reversed()`

returns a new list with elements of`L`

in reverse order;`L.sorted()`

and`L.sortedDescending()`

returns a new list with elements of`L`

in nondecreasing and nonincreasing sorted order;`L + e`

returns a new list containing elements of`L1`

with element`e`

appended at end;`L1 + L2`

returns a new list containing the concatenation of`L1`

and`L2`

;`L.indexOf(e)`

and`L.lastIndexOf(e)`

return the first and last index whose element is equal to`e`

, or -1 if no such index exists;

- A
*mutable list*is a list whose sequence of elements can be modified, i.e., added, removed, or replaced. It can do all that immutable lists can, but it also supports additional functions not supported by immutable lists. - Here are some extra functions callable on mutable lists
`m`

,`m1`

,`m2`

:`m.add(e)`

adds element`e`

(of the right type) to the end of`m`

;`m.add(i, e)`

adds element`e`

(of the right type) at index`i`

of`m`

;`m1.addAll(m2)`

adds all elements of`m2`

to the end of`m1`

;`m1.addAll(i, m2)`

adds all elements of`m2`

at index`i`

of`m1`

;`m.remove(e)`

removes an element equal to`e`

from`m`

, if one exists;`m.removeAt(i)`

removes an element a valid index`i`

from`m`

;`m.clear()`

removes all elements from`m`

;`m.reverse()`

reverses the order of elements in`m`

;`m.sort()`

and`m.sortDescending()`

sorts the elements of`m`

in nondecreasing and nonincreasing order;`m.shuffle()`

rearranges the elements of`m`

in a random order;

Here is an example usage of mutable lists.

`>>> val m1 = mutableListOf<String>() >>> m1 [] >>> val m2 = mutableListOf("Alice", "Bob", "Ben", "Charlie") >>> m2 [Alice, Bob, Ben, Charlie] >>> m2.add("Dave") true >>> m2 [Alice, Bob, Ben, Charlie, Dave] >>> m2.removeAt(2) Ben >>> m2 [Alice, Bob, Charlie, Dave] >>> m2.sortDescending() >>> m2 [Dave, Charlie, Bob, Alice] >>> m2.shuffle() >>> m2 [Ben, Alice, Bob, Charlie]`