Dart Closures
A closure is a function that captures variables from the scope where it was created. The function keeps access to those variables after the outer code has finished.
A counter factory
makeCounter builds a function that remembers count. The first counter reaches 2, and a second counter starts again at 1.
int Function() makeCounter() {
var count = 0;
return () {
count++;
return count;
};
}
void main() {
var next = makeCounter();
print(next());
print(next());
var fresh = makeCounter();
print(fresh());
}Seeing a later change
The closure reads message when it runs, not when it was made. Changing message between the two calls changes the second print.
void main() {
var message = 'start';
var show = () {
print(message);
};
show();
message = 'updated';
show();
}One capture per loop turn
Each turn of the loop builds a closure around that turn value of i. The stored closures print 0, 1, and 2 in order.
void main() {
var readers = <int Function()>[];
for (var i = 0; i < 3; i++) {
readers.add(() => i);
}
print(readers[0]());
print(readers[1]());
print(readers[2]());
}Example
int Function(int) makeTotal() {
var total = 0;
return (int amount) {
total += amount;
return total;
};
}
void main() {
var add = makeTotal();
print(add(5));
print(add(3));
print(add(10));
}Key points
- A closure remembers the variables it captures, not just copies of their values.
- Each call to a factory function creates a fresh set of captured variables.
- Two closures made by two calls share nothing with each other.
- A change to a captured variable after creation is visible when the closure runs later.
- A closure built in a loop captures the value from its own iteration.
In this example, makeTotal returns a closure that captures total. Each call adds its amount to the same captured total. The prints show the running total growing from 5 to 8 to 18.
Try it Yourself
Edit the code, then press Run.
Running is simulated · DartPad
Exercise
A counter factory is called twice, making counter A and counter B. A runs twice and B runs once. What does the call to B print?