Functions
Defining a function
Section titled “Defining a function”fn defines a function. (def is an alias.) The body runs until end.
fn greet(name) println "Hello, ${name}!"end
greet("Kiwi") # Hello, Kiwi!Return values
Section titled “Return values”A function returns the value of the last expression it evaluates, so most functions don’t need return. Use return to leave early. A bare return returns null.
fn add(a, b) a + bend
fn absolute(n) return -n when n < 0 nend
println add(3, 4) # 7println absolute(-5) # 5To return several values, return a list and unpack it:
fn min_max(values) [values.min(), values.max()]end
low, high = min_max([4, 1, 9])println "${low}..${high}" # 1..9Default values
Section titled “Default values”A parameter can have a default, used when the argument is left out. Defaults are evaluated on each call, so a default list or hashmap is fresh every time, and a default can refer to earlier parameters.
fn greet(name = "stranger", greeting = "Hello") "${greeting}, ${name}!"end
println greet() # Hello, stranger!println greet("Ada") # Hello, Ada!
fn box(width, height = width) "${width}x${height}"end
println box(3) # 3x3Named arguments
Section titled “Named arguments”Any argument can be passed by name, as name: value or name = value. Positional arguments fill the remaining parameters from left to right, so the two styles mix freely.
fn connect(host, port = 80, secure = false) "${secure ? "https" : "http"}://${host}:${port}"end
println connect("example.com") # http://example.com:80println connect("example.com", secure: true, port: 443) # https://example.com:443println connect(port = 8080, host = "localhost") # http://localhost:8080Passing a name that isn’t a parameter is an error.
Kiwi checks the arguments a call passes. Leaving out a parameter that has no default, passing more positional arguments than there are parameters, or passing a parameter both by position and by name is an error:
fn connect(host, port = 80) "${host}:${port}"end
connect("example.com", 80, true) # ParameterCountMismatchError: Expected 1 to 2 but received 3.Lambdas are more forgiving, so they work as callbacks: a missing argument is null and extra arguments are ignored.
Variadic parameters
Section titled “Variadic parameters”Prefix the last parameter with * to collect any remaining positional arguments into a list:
fn sum(*numbers) total = 0 for n in numbers do total += n end totalend
println sum() # 0println sum(1, 2, 3) # 6
fn tag(label, *values) "${label}: ${values}"end
println tag("nums", 1, 2) # nums: [1, 2]At the call site, *list spreads a list into separate arguments:
fn add3(a, b, c) a + b + cend
args = [1, 2, 3]println add3(*args) # 6Hoisting
Section titled “Hoisting”Top-level functions are registered before the script starts running, so a function can be called above the line that defines it. Mutual recursion works the same way.
println is_even(10) # true
fn is_even(n) return true when n == 0 is_odd(n - 1)end
fn is_odd(n) return false when n == 0 is_even(n - 1)endFunctions defined inside other functions or blocks are created when that code runs.
Recursion
Section titled “Recursion”fn factorial(n) return 1 when n <= 1 n * factorial(n - 1)end
println factorial(10) # 3628800Recursion is limited to roughly 500 nested calls; deeper recursion raises a Stack overflow error. Rewrite very deep recursion as a loop.
Functions as values
Section titled “Functions as values”A named function is a value. Pass it to another function, store it in a variable or collection, or return it. Call it like any lambda.
fn shout(text) text.uppercase() + "!"end
fn apply_twice(f, value) f(f(value))end
println apply_twice(shout, "hi") # HI!!println ["a", "b"].map(shout) # ["A!", "B!"]
handlers = {loud: shout}println handlers["loud"]("hey") # HEY!Nested functions
Section titled “Nested functions”A fn inside another function is a helper for that function. It exists only while the outer call runs:
fn summarize(values) fn average(xs) xs.sum() / xs.size() end
"n=${values.size()} mean=${average(values)}"end
println summarize([2, 4, 6]) # n=3 mean=4Related pages
Section titled “Related pages”- Lambdas for anonymous functions and closures.
- Type Hints for annotating parameters and return values.
- Generators for functions that
yielda sequence. - Decorators for wrapping functions with
@name. - Scoping for how functions see variables.