Closures
A lambda is an anonymous function, written as a parameter list
followed by => and an expression body. Lambdas are
commonly passed to higher-order functions such as map and
filter:
void main() {
var numbers = List([0, 1, 2, 3, 4]);
var even = numbers.filter(n => n % 2 == 0).toList();
println(even); // prints [0, 2, 4]
var doubled = even.map(n => n * 2).toList();
println(doubled); // prints [0, 4, 8]
}When a lambda is passed directly to a function, its parameter types are inferred from the expected function pointer type. When there is no expected type, for example when storing a lambda in a variable, the parameter types must be written explicitly:
int apply(int(int) f, int x) {
return f(x);
}
void main() {
var triple = (int n) => n * 3;
println(triple(14)); // prints 42
println(apply(n => n + 1, 41)); // prints 42, parameter type inferred
}A lambda body can also be a block with statements. In that case the
=> before the brace is optional:
void main() {
var f = (int x, int y) {
var sum = x + y;
return sum * 2;
};
println(f(10, 11)); // prints 42
}Captures
Stored lambdas capture variables from the enclosing scope by copy:
void main() {
int threshold = 100;
var isBig = (int n) => n >= threshold;
println(isBig(42)); // prints false
println(isBig(101)); // prints true
}Capturing lambdas cannot convert to function pointer types; they can
be stored in variables and called directly. They can also be passed to
generic higher-order functions such as filter and
map, which are generic over the callback type so each call
site is specialized for its lambda with no dynamic allocation for the
closure:
void main() {
var numbers = List([0, 1, 2, 3, 4]);
int threshold = 2;
println(numbers.filter(n => n >= threshold)); // prints [2, 3, 4]
}Constants
A lambda passed to a method on a constant receives constant elements,
so its borrow parameters bind const: reading through them works, but
writing is rejected. This also applies through call chains, which
conservatively includes chains through copying calls such as
toList(); bind such a result to a variable first to work
with it mutably:
void main() {
const arr = [1, 2, 3];
println(arr.map(n => *n + 1)); // prints [2, 3, 4]
// arr.map(n => { *n = 99; return *n; }); // error: cannot assign to constant
}