Kotlin

Higher-Order Functions and Lambdas

Swift

Higher-Order Functions

                  fun <T, R> Collection<T>.fold(
    initial: R, 
    combine: (acc: R, nextElement: T) -> R
): R {
    var accumulator: R = initial
    for (element: T in this) {
        accumulator = combine(accumulator, element)
    }
    return accumulator
}
                
                    func <T, R> Collection<T>.fold(
    initial: R, 
    combine: (acc: R, nextElement: T) -> R
): R {
    var accumulator: R = initial
    for (element: T in this) {
        accumulator = combine(accumulator, element)
    }
    return accumulator
}
                  
                  val items = listOf(1, 2, 3, 4, 5)
​
// Lambdas are code blocks enclosed in curly braces.
items.fold(0, { 
    // When a lambda has parameters, they go first, followed by '->'
    acc: Int, i: Int -> 
    print("acc = $acc, i = $i, ") 
    val result = acc + i
    println("result = $result")
    // The last expression in a lambda is considered the return value:
    result
})
​
// Parameter types in a lambda are optional if they can be inferred:
val joinedToString = items.fold("Elements:", { acc, i -> acc + " " + i })
​
// Function references can also be used for higher-order function calls:
val product = items.fold(1, Int::times)
​
                
                    let items = [1, 2, 3, 4, 5]
​
// Lambdas are code blocks enclosed in curly braces.
items.fold(0, { 
    // When a lambda has parameters, they go first, followed by '->'
    acc: Int, i: Int -> 
    print("acc = $acc, i = $i, ") 
    let result = acc + i
    print("result = $result")
    // The last expression in a lambda is considered the return value:
    result
})
​
// Parameter types in a lambda are optional if they can be inferred:
let joinedToString = items.fold("Elements:", { acc, i -> acc + " " + i })
​
// Function references can also be used for higher-order function calls:
let product = items.fold(1, Int::times)
​
                  

Function types

                  typealias ClickHandler = (Button, ClickEvent) -> Unit
                
                    typealias ClickHandler = (Button, ClickEvent) -> Unit
                  

Instantiating a function type

                  class IntTransformer: (Int) -> Int {
    override operator fun invoke(x: Int): Int = TODO()
}
​
val intFunction: (Int) -> Int = IntTransformer()
                
                    class IntTransformer: (Int) -> Int {
    override operator func invoke(x: Int) -> Int = TODO()
}
​
let intFunction: (Int) -> Int = IntTransformer()
                  
                  val a = { i: Int -> i + 1 } // The inferred type is (Int) -> Int
                
                    let a = { i: Int -> i + 1 } // The inferred type is (Int) -> Int
                  
                  val repeatFun: String.(Int) -> String = { times -> this.repeat(times) }
val twoParameters: (String, Int) -> String = repeatFun // OK
​
fun runTransformation(f: (String, Int) -> String): String {
    return f("hello", 3)
}
val result = runTransformation(repeatFun) // OK
​
                
                    let repeatFun: String.(Int) -> String = { times -> this.repeat(times) }
let twoParameters: (String, Int) -> String = repeatfunc // OK
​
func runTransformation(f: (String, Int) -> String) -> String {
    return f("hello", 3)
}
let result = runTransformation(repeatFun) // OK
​
                  

Invoking a function type instance

                  val stringPlus: (String, String) -> String = String::plus
val intPlus: Int.(Int) -> Int = Int::plus
​
println(stringPlus.invoke("<-", "->"))
println(stringPlus("Hello, ", "world!")) 
​
println(intPlus.invoke(1, 1))
println(intPlus(1, 2))
println(2.intPlus(3)) // extension-like call
​
                
                    let stringPlus: (String, String) -> String = String::plus
let intPlus: Int.(Int) -> Int = Int::plus
​
print(stringPlus.invoke("<-", "->"))
print(stringPlus("Hello, ", "world!")) 
​
print(intPlus.invoke(1, 1))
print(intPlus(1, 2))
print(2.intPlus(3)) // extension-like call
​
                  

Lambda Expressions and Anonymous Functions

                  max(strings, { a, b -> a.length < b.length })
                
                    max(strings, { a, b -> a.length < b.length })
                  
                  fun compare(a: String, b: String): Boolean = a.length < b.length
                
                    func compare(a: String, b: String): Boolean = a.length < b.length
                  

Lambda expression syntax

                  val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
                
                    let sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
                  
                  val sum = { x: Int, y: Int -> x + y }
                
                    let sum = { x: Int, y: Int -> x + y }
                  

Passing trailing lambdas

                  val product = items.fold(1) { acc, e -> acc * e }
                
                    let product = items.fold(1) { acc, e -> acc * e }
                  
                  run { println("...") }
                
                    run { print("...") }
                  

it: implicit name of a single parameter

                  ints.filter { it > 0 } // this literal is of type '(it: Int) -> Boolean'
                
                    ints.filter { $0 > 0 } // this literal is of type '(it: Int) -> Boolean'
                  

Returning a value from a lambda expression

                  ints.filter {
    val shouldFilter = it > 0 
    shouldFilter
}
​
ints.filter {
    val shouldFilter = it > 0 
    return@filter shouldFilter
}
                
                    ints.filter {
    let shouldFilter = $0 > 0
    shouldFilter
}
​
ints.filter {
    let shouldFilter = $0 > 0
    return@filter shouldFilter
}

                  
                  strings.filter { it.length == 5 }.sortedBy { it }.map { it.toUpperCase() }
                
                    strings.filter { it.length == 5 }.sortedBy { $0 }.map { it.toUpperCase() }
                  

Underscore for unused variables (since 1.1)

                  map.forEach { _, value -> println("$value!") }
                
                    map.forEach { _, value -> print("$value!") }
                  

Anonymous functions

                  fun(x: Int, y: Int): Int = x + y
                
                    fun(x: Int, y: Int) -> Int = x + y
                  
                  fun(x: Int, y: Int): Int {
    return x + y
}
                
                    fun(x: Int, y: Int) -> Int {
    return x + y
}
                  
                  ints.filter(fun(item) = item > 0)
                
                    ints.filter(fun(item) = item > 0)
                  

Closures

                  var sum = 0
ints.filter { it > 0 }.forEach {
    sum += it
}
print(sum)
                
                    var sum = 0
ints.filter { $0 > 0 }.forEach {
    sum += it
}
print(sum)
                  

Function literals with receiver

                  val sum: Int.(Int) -> Int = { other -> plus(other) }
                
                    let sum: Int.(Int) -> Int = { other -> plus(other) }
                  
                  val sum = fun Int.(other: Int): Int = this + other
                
                    let sum = func Int.(other: Int) -> Int = this + other
                  
                  class HTML {
    fun body() { ... }
}
​
fun html(init: HTML.() -> Unit): HTML {
    val html = HTML()  // create the receiver object
    html.init()        // pass the receiver object to the lambda
    return html
}
​
html {       // lambda with receiver begins here
    body()   // calling a method on the receiver object
}
                
                    class HTML {
    func body() { ... }
}
​
func html(init: HTML.() -> Unit): HTML {
    let html = HTML()  // create the receiver object
    html.init()        // pass the receiver object to the lambda
    return html
}
​
html {       // lambda with receiver begins here
    body()   // calling a method on the receiver object
}