पाठ 8 / 25

Closures, Function Types and Tear-offs

Use anonymous functions, closures, typedefs and tear-offs.

Functions as values

Anonymous functions (lambdas) are written (params) { body } or (params) => expression and are passed everywhere: list.map((p) => p.title), event handlers, sorting comparators. A closure captures variables from its surrounding scope and can read and modify them later, which powers counters, callbacks and memoisation. Function types are written like int Function(int a, int b), and typedef gives them names: typedef PriceRule = double Function(double price);, making APIs that accept callbacks readable. A tear-off turns an existing function or method into a function value without writing a lambda: names.forEach(print) or items.map(Product.fromJson), and constructor tear-offs (List.generate(3, Item.new)) work too. Tear-offs are preferred over wrapper lambdas such as (x) => print(x), which the linter flags. Closures in loops capture a fresh variable per iteration in for loops, avoiding a classic JavaScript bug.

Closures, typedefs and tear-offs

Building pricing rules as functions and composing them.

typedef PriceRule = double Function(double price);

PriceRule percentOff(double percent) => (price) => price * (1 - percent / 100);   // returns a closure
PriceRule flatOff(double amount) => (price) => price - amount < 0 ? 0 : price - amount;

double applyAll(double price, List<PriceRule> rules) =>
    rules.fold(price, (current, rule) => rule(current));

int Function() makeCounter() {
  var count = 0;
  return () => ++count;            // captures and modifies count
}

void main() {
  final festive = [percentOff(10), flatOff(50)];
  print(applyAll(1000, festive));   // 850.0

  final next = makeCounter();
  next();
  print(next());                    // 2

  final titles = ['pen', 'ink'];
  titles.map((t) => t.toUpperCase()).forEach(print);   // tear-off of print
}

Recipes as index cards

Function values are recipe cards you can hand around: "apply 10% off", "subtract Rs 50". A checkout can take a stack of cards and apply them in order without knowing what each one does inside.

त्वरित जाँच: What is a tear-off in Dart?

  • A way to delete a function
  • A type of exception
  • A collection literal
  • Using a function or method name as a function value without wrapping it in a lambda
Answer

Using a function or method name as a function value without wrapping it in a lambda — Tear-offs like list.forEach(print) pass existing functions directly.