Functions and closures
Declare a function with typed parameters, defaults and labels, write a closure, and pass it as the last argument of a call.
A function is declared with fn. A closure is a piece of code you can store in a binding or hand to another function.
Goal#
At the end of this page you can declare a function with defaults and labels, write a closure, and pass one to a call.
Declare a function#
fn distance(x: Int, y: Int): Int {
const dx = x * x
const dy = y * y
dx + dy
}
print distance(3, 4)
// prints 25Every parameter has a type. The result is the last line of the body, and its type can be left out: the compiler
works it out. A public function writes it, so a caller in another file sees it without reading the body. A function
can be called above the line it is declared on.
Defaults and labels#
fn connect(host: String, port: Int = 5432, timeout: Int = 30): String {
"{host}:{port}, timeout {timeout}s"
}
print connect("localhost")
print connect("localhost", 3306)
print connect("localhost", timeout: 10)
// prints localhost:5432, timeout 30s
// prints localhost:3306, timeout 30s
// prints localhost:5432, timeout 10sA parameter with a default can be left out. A call can name a parameter, timeout: 10, to skip the ones before it.
Closures#
const double = { x: Int => x * 2 }
const triple: (Int) => Int = { _ * 3 }
print double(21)
print triple(7)
// prints 42
// prints 21A closure is always written { parameters => body }. When the type is clear from where the closure goes, you can leave
the parameters out and write _ for the first one. A { where a value is expected is always a closure, never a
block. return inside a closure leaves the closure, not the function around it.
The last argument can follow the call#
const numbers = [1, 2, 3, 4]
const doubled = numbers.map { _ * 2 }
const total = numbers.fold 0 { sum, number => sum + number }
print doubled.toList()
print total
// prints [2, 4, 6, 8]
// prints 10When the last parameter is a function, the closure can stand after the call instead of inside the parentheses. This is
how test "name" { ... } and your own control structures read like built-in syntax. A call without arguments still
needs (): distance alone is the function itself, not a call.
Next#
- Types and methods - your own types, and functions that belong to them.
- Declaring a function - the exact rules.
- Closures - what a closure captures, and when.