Skip to content

Closures & Lambdas

Inline Lambdas

wyn
nums = [1, 2, 3, 4, 5]
doubled = nums.map(fn(x: int) -> int { return x * 2 })
big = nums.filter(fn(x: int) -> bool { return x > 3 })

Void Lambdas

Lambdas without a return type - for side effects:

wyn
items = [1, 2, 3]
items.each(fn(x: int) { print(x.to_string()) })

5.times(fn() { print("tick") })

Multiline Lambdas

Lambda bodies can contain multiple statements:

wyn
var processed = nums.map(fn(x: int) -> int {
    var squared = x * x
    var adjusted = squared + 1
    return adjusted
})

nums.each(fn(x: int) {
    var label = "item: " + x.to_string()
    print(label)
})

Chained Operations

wyn
result = [1, 2, 3, 4, 5]
    .filter(fn(x: int) -> bool { return x > 2 })
    .map(fn(x: int) -> int { return x * 10 })
print(result.join(", "))  // 30, 40, 50

Closures with Captures

Closures capture variables from the enclosing scope:

wyn
x = 10
add_x = fn(n: int) -> int { return n + x }
print(add_x(5).to_string())  // 15

Returning Closures

Functions can return closures:

wyn
fn make_adder(n: int) -> fn(int) -> int {
    return fn(x: int) -> int { return x + n }
}

add5 = make_adder(5)
add10 = make_adder(10)
print(add5(3).to_string())   // 8
print(add10(3).to_string())  // 13

Closures as Arguments

wyn
fn apply(arr: [int], f: fn(int) -> int) -> [int] {
    return arr.map(f)
}

result = apply([1, 2, 3], fn(x: int) -> int { return x * x })
// result = [1, 4, 9]

Sort with Comparator

wyn
nums = [5, 3, 1, 4, 2]
sorted = nums.sort(fn(a: int, b: int) -> int { return a - b })

Mutable Captures

Closures capture variables by reference - mutations are visible to the caller:

wyn
count = 0
items = [1, 2, 3, 4, 5]
items.each(fn(x: int) { count = count + x })
print(count.to_string())  // 15
wyn
n = 0
5.times(fn() { n = n + 1 })
print(n.to_string())  // 5
wyn
count = 0
inc = fn() -> int {
    count = count + 1
    return count
}
print(inc().to_string())  // 1
print(inc().to_string())  // 2
print(inc().to_string())  // 3

This works with multi-statement block bodies. The captured variable is modified in-place - subsequent calls see the updated value.

wyn
total = 0
items = [10, 20, 30]
add_to_total = fn(n: int) {
    total = total + n
}
for item in items {
    add_to_total(item)
}
print(total.to_string())  // 60

Arrow Syntax

For single-expression lambdas, use =>:

wyn
double = fn(x: int) => x * 2
nums = [1, 2, 3].map(fn(x: int) => x * 10)

See Also

MIT License - v1.21.0