flutter
/

Dart Higher-Order Functions – Functions as First-Class Citizens

Last Sync: Today

On this page

7
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

Dart Higher-Order Functions – Functions as First-Class Citizens

What are Higher-Order Functions?

A higher‑order function is a function that takes one or more functions as arguments, returns a function, or both. In Dart, functions are first‑class objects, meaning they can be assigned to variables, passed as arguments, and returned from other functions. Higher‑order functions are a cornerstone of functional programming and enable powerful, expressive code patterns.

Built‑in Higher‑Order Functions in Dart

Dart's collection classes come with many higher‑order functions. The most common ones are:

    • forEach – performs an action on each element.
    • map – transforms each element into a new value (returns a lazy iterable).
    • where – filters elements based on a condition.
    • reduce – combines all elements into a single value.
    • fold – similar to reduce but with an initial value.
    • any / every – test a condition on elements.
    • firstWhere / lastWhere – find elements.
DARTRead-only
1
void main() {
  var numbers = [1, 2, 3, 4, 5];

  // forEach
  numbers.forEach((n) => print(n));

  // map
  var squares = numbers.map((n) => n * n).toList();
  print(squares); // [1, 4, 9, 16, 25]

  // where
  var even = numbers.where((n) => n % 2 == 0).toList();
  print(even); // [2, 4]

  // reduce
  var sum = numbers.reduce((a, b) => a + b);
  print(sum); // 15

  // fold (with initial value)
  var product = numbers.fold(1, (a, b) => a * b);
  print(product); // 120
}

Writing Your Own Higher‑Order Function

You can define your own functions that accept other functions. This is useful for creating reusable algorithms where the specific behavior can be supplied by the caller.

DARTRead-only
1
void repeat(int times, void Function(int) action) {
  for (int i = 0; i < times; i++) {
    action(i);
  }
}

void main() {
  repeat(3, (index) {
    print('Hello, iteration $index');
  });
}
// Output:
// Hello, iteration 0
// Hello, iteration 1
// Hello, iteration 2

The parameter action is a function that takes an int and returns void. You can pass any matching function, including lambdas.

Returning Functions (Function Factories)

A higher‑order function can also return a function. This is useful for creating function factories or closures with pre‑configured behavior.

DARTRead-only
1
Function makeMultiplier(double factor) {
  return (double value) => value * factor;
}

void main() {
  var doubleIt = makeMultiplier(2);
  var tripleIt = makeMultiplier(3);

  print(doubleIt(5)); // 10.0
  print(tripleIt(5)); // 15.0
}

Here, makeMultiplier returns a lambda that captures factor – a classic example of a closure.

Type Aliases for Function Types

To improve readability, you can define a typedef for a function type. This makes your code more self‑documenting.

DARTRead-only
1
typedef IntTransformer = int Function(int);

int applyTransformer(int value, IntTransformer transformer) {
  return transformer(value);
}

void main() {
  int square(int x) => x * x;
  print(applyTransformer(5, square)); // 25
}

Practical Example: Custom Filter Function

DARTRead-only
1
List<T> myFilter<T>(List<T> list, bool Function(T) predicate) {
  List<T> result = [];
  for (var item in list) {
    if (predicate(item)) {
      result.add(item);
    }
  }
  return result;
}

void main() {
  var numbers = [1, 2, 3, 4, 5];
  var even = myFilter(numbers, (n) => n % 2 == 0);
  print(even); // [2, 4]

  var names = ['Alice', 'Bob', 'Charlie'];
  var shortNames = myFilter(names, (name) => name.length <= 3);
  print(shortNames); // [Bob]
}

Key Takeaways

    • Higher‑order functions accept or return other functions, enabling flexible and reusable code.
    • Dart provides many built‑in higher‑order functions for collections (map, where, reduce, etc.).
    • You can create your own higher‑order functions to encapsulate algorithms.
    • Returning functions (function factories) allows you to generate customized behavior.
    • Use typedef to give meaningful names to function types.

Try it yourself

void main() {
  // Define a higher-order function that applies a transformation to each element
  List<int> applyToList(List<int> list, int Function(int) transform) {
    return list.map(transform).toList();
  }

  var numbers = [1, 2, 3];
  var doubled = applyToList(numbers, (n) => n * 2);
  print(doubled); // [2, 4, 6]
}

Test Your Knowledge

Q1
of 4

What is a higher‑order function?

A
A function that is defined inside another function
B
A function that takes another function as an argument or returns a function
C
A function that has multiple parameters
D
A function that uses the `async` keyword
Q2
of 4

Which of the following is a built‑in higher‑order function in Dart?

A
print()
B
map()
C
sqrt()
D
main()
Q3
of 4

What does the following code return? Function makeAdder(int addBy) { return (int i) => i + addBy; } void main() { var add5 = makeAdder(5); print(add5(10)); }

A
5
B
10
C
15
D
Error
Q4
of 4

Which keyword is used to define a type alias for a function type?

A
alias
B
typedef
C
using
D
function

Frequently Asked Questions

What is the difference between a callback and a higher‑order function?

A callback is a function passed as an argument to another function, to be executed later. A higher‑order function is the function that receives or returns a function. So callbacks are often used with higher‑order functions.

Can a higher‑order function return multiple functions?

It returns one function, but that function can itself be a higher‑order function, enabling currying or multi‑level factories.

Are lambdas the only way to pass a function to a higher‑order function?

No, you can also pass named functions, static methods, or even constructors, as long as the signature matches.

How do I specify the return type of a function parameter?

Use the full function type syntax: void Function(int) callback for a function taking an int and returning void. You can also use typedef for clarity.

What is a practical use case for returning a function?

Examples: creating configuration functions (like makeMultiplier), building middleware chains, implementing partial application, or generating event handlers with pre‑set parameters.

Do higher‑order functions impact performance?

In most cases, no. Dart's optimizing compiler can inline simple functions. However, excessive creation of closures in tight loops may have overhead, but it's rarely a concern.

Previous

dart lambdas

Next

dart closures

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.