Functions
Functions are first-class values. Define them with func.
func add(a, b) { return a + b}
print(add(2, 3)) // 5Default parameters
Section titled “Default parameters”Parameters can have default values. Non-default parameters must come first.
func greet(name, greeting = "Hello") { print("%{greeting}, %{name}!")}
greet("Ada") // Hello, Ada!greet("Ada", "Welcome") // Welcome, Ada!Rest parameters
Section titled “Rest parameters”Use ...name as the last parameter to collect remaining arguments into an array:
func log(level, ...messages) { print("[" + level + "]", messages.join(" "))}
log("INFO", "server", "started", "on", "8080")// [INFO] server started on 8080If no extra arguments are passed, the rest parameter is an empty array.
Named arguments
Section titled “Named arguments”Pass arguments by name using name: value syntax. Positional arguments must come first.
func createUser(name, age, role = "user") { return {name: name, age: age, role: role}}
createUser("Ada", 36) // all positionalcreateUser("Ada", role: "admin", age: 36) // mixedcreateUser(name: "Ada", age: 36) // all namedNamed arguments work with lambdas, constructors, and the pipe operator:
func format(value, prefix = "", suffix = "") { return prefix + str(value) + suffix}42 |> format(suffix: "!") // "42!"Unknown or duplicate parameter names throw a runtime error. Native built-in functions do not support named arguments.
Implicit nil return
Section titled “Implicit nil return”Functions without an explicit return return nil.
Closures
Section titled “Closures”Functions capture their enclosing scope:
func makeCounter() { let count = 0 func increment() { count = count + 1 return count } return increment}
let counter = makeCounter()print(counter()) // 1print(counter()) // 2print(counter()) // 3Recursion
Section titled “Recursion”func fib(n) { if (n <= 1) { return n } return fib(n - 1) + fib(n - 2)}print(fib(10)) // 55Functions as values
Section titled “Functions as values”func apply(f, x) { return f(x)}
func double(n) { return n * 2 }
print(apply(double, 21)) // 42Decorators
Section titled “Decorators”Decorators wrap a function using @ syntax. @dec func f(){} desugars to func f(){}; f = dec(f).
func log(fn) { return lam{ ...args in print("calling " + str(fn)) return fn(...args) }}
@logfunc add(a, b) { return a + b }
add(2, 3) // prints "calling <function add>", returns 5Multiple decorators are applied bottom-up:
@auth@logfunc handler(req) { ... }// equivalent to: handler = auth(log(handler))Decorators can take arguments:
func role(required) { return lam{ fn in return lam{ ...args in print("checking role: " + required) return fn(...args) } }}
@role("admin")func deleteUser(id) { ... }Decorators also work on class methods (both instance and static).
Lambdas
Section titled “Lambdas”Lambdas are anonymous functions defined inline with lam{ params in body }.
Single expression (auto-returned)
Section titled “Single expression (auto-returned)”let double = lam{ x in x * 2 }let add = lam{ a, b in a + b }
print(double(5)) // 10print(add(3, 4)) // 7A single-expression lambda automatically returns its result.
Multi-line (explicit return)
Section titled “Multi-line (explicit return)”let process = lam{ x, y in let sum = x + y let product = x * y return {sum: sum, product: product}}No parameters
Section titled “No parameters”let sayHi = lam{ in print("hello!") }sayHi()Lambdas as callbacks
Section titled “Lambdas as callbacks”let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]let evens = filter(nums, lam{ n in n % 2 == 0 })let squares = map(nums, lam{ n in n * n })
print(evens) // [2, 4, 6, 8, 10]print(squares) // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]Closures
Section titled “Closures”Lambdas capture their enclosing scope:
func makeMultiplier(factor) { return lam{ x in x * factor }}
let triple = makeMultiplier(3)print(triple(5)) // 15Lambdas in maps
Section titled “Lambdas in maps”let actions = { double: lam{ x in x * 2 }, negate: lam{ x in -x }}print(actions.double(21)) // 42Pipe operator with functions
Section titled “Pipe operator with functions”The pipe operator |> passes the left side as the first argument:
let result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] |> filter(lam{ n in n % 2 == 0 }) |> map(lam{ n in n * n }) |> sortprint(result) // [4, 16, 36, 64, 100]Functions designed for pipe usage:
| Function | Description |
|---|---|
filter(arr, predicate) | Keep elements where predicate returns truthy |
map(arr, transform) | Transform each element |
each(arr, fn) | Call fn on each element (side effects), returns the array |
sort(arr) | Return sorted copy |
keys(map) | Return array of map keys |
values(map) | Return array of map values |