Koans
Function
- Keyword
fun
for declaring a function - Classical way : return type at the end of the function declaration and code contains a
return
statementfun classicWay(): Int { return 1 }
- On the same line as the function declaration, directly return the result
fun lessClassic(): Int = 1
- Return type can be omitted
fun withReturnTypeInferrence() = 1
Named arguments
- When declaring a function, you can have several parameters
fun reformat( str: String, normalizeCase: Boolean, upperCaseFirstLetter: Boolean, divideByCamelHumps: Boolean , wordSeparator: Char, ) { /*...*/ }
- When calling this function, parameter name can be specified
- You can freely change the order they are listed in
reformat( "String!", false, upperCaseFirstLetter = false, divideByCamelHumps = true, '_' )
Default arguments
- Function parameters can have default values, which are used when you skip the corresponding argument.
- Reduces the number of overloads
- Overriding methods always use the same default parameter values as the base method
fun foo( bar: Int = 0, baz: Int, ) { /*...*/ }
foo(baz = 1) // The default value bar = 0 is used
Lambda
- Lambda functions (“lambdas”) are a simple way to create functions ad-hoc
- Can be denoted very concisely in many cases thanks to type inference and the implicit
it
variable.
val upperCase1: (String) -> String = { str: String -> str.uppercase() } // 1
val upperCase2: (String) -> String = { str -> str.uppercase() } // 2
val upperCase3 = { str: String -> str.uppercase() } // 3
// val upperCase4 = { str -> str.uppercase() } // 4
val upperCase5: (String) -> String = { it.uppercase() } // 5
val upperCase6: (String) -> String = String::uppercase // 6
- A lambda in all its glory, with explicit types everywhere. The lambda is the part in curly braces, which is assigned to a variable of type
(String) -> String
(a function type). - Type inference inside lambda: the type of the lambda parameter is inferred from the type of the variable it’s assigned to.
- Type inference outside lambda: the type of the variable is inferred from the type of the lambda parameter and return value.
- You cannot do both together, the compiler has no chance to infer the type that way.
- For lambdas with a single parameter, you don’t have to explicitly name
it
. Instead, you can use the implicitit
variable. This is especially useful when the type ofit
can be inferred (which is often the case). - If your lambda consists of a single function call, you may use function pointers
::
Variables
- Immutable reference : variable cannot be reassigned, but the object is not immutable
val a: Int = 1 // immediate assignment
val b = 2 // `Int` type is inferred
val c: Int // Type required when no initializer is provided
c = 2
- Mutable reference : variable can be reassigned
var x = 5 // `Int` type is inferred
Triple-quoted string
- A String literal that can contains newlines and arbitrary text
- Raw string is delimited by
"""
- To remove leading whitespace from raw strings, use the
trimMargin()
function - By default
|
is the prefix that should be deleted
val text = """
|Tell me and I forget.
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()
For loop
for
loop iterates through anything that provides an iterator- Iterates through anything that provides an iterator
for (item in collection) print(item)
val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
println(item)
}
Conditional expression
- No ternary operator
condition ? then : else
if
may be used as an expression
fun max(a: Int, b: Int) = if (a > b) a else b
- is Equivalent to :
fun max(a: Int, b: Int): Int {
if (a > b)
return a
else
return b
}
String template
- Allow to execute some code a part of a string literal
var a = 1
// simple name in template:
val s1 = "a is $a"
a = 2
// arbitrary expression in template:
val s2 = "${s1.replace("is", "was")}, but now is $a"