Functional Programming in Dart
Dart is primarily an object-oriented language, but it also supports functional programming (FP) principles. Functional programming is a paradigm that treats computation as the evaluation of pure functions and avoids shared mutable state.
In this guide, we’ll explore functional programming in Dart, covering higher-order functions, first-class functions, pure functions, immutability, and more.
🔹 Why Use Functional Programming in Dart?
✅ Improved Readability — Functions are self-contained and predictable.
✅ Easier Debugging & Testing — No side effects, making unit testing simpler.
✅ Concurrency-Friendly — Avoids race conditions in multithreading.
✅ Less Complexity — Less dependency on mutable state and class hierarchies.
1️⃣ First-Class Functions in Dart
Dart treats functions as first-class citizens, meaning you can:
✔️ Assign functions to variables.
✔️ Pass functions as arguments.
✔️ Return functions from other functions.
Example: Assigning Functions to Variables
void greet(String name) {
print("Hello, $name!");
}
void main() {
var sayHello = greet; // Assign function to variable
sayHello("Alice");
}Example: Passing Functions as Arguments
void executeFunction(Function action) {
action();
}
void sayHi() {
print("Hi there!");
}
void main() {
executeFunction(sayHi); // Passing function as an argument
}2️⃣ Higher-Order Functions (HOFs)
A higher-order function is a function that takes another function as a parameter or returns a function.
Example: Function Returning a Function
Function multiplyBy(int factor) {
return (int number) => number * factor;
}
void main() {
var doubleNumber = multiplyBy(2);
print(doubleNumber(5)); // Output: 10
}3️⃣ Anonymous Functions (Lambda or Arrow Functions)
Dart supports anonymous functions (also called lambda functions or closures).
Example: Lambda Function (Short Syntax)
var square = (int x) => x * x;
void main() {
print(square(4)); // Output: 16
}💡 Note: {} can also be used:
var add = (int a, int b) {
return a + b;
};
print(add(3, 4)); // Output: 74️⃣ Pure Functions (No Side Effects)
A pure function:
✔️ Always returns the same output for the same input.
✔️ Has no side effects (doesn’t modify external state).
Example of a Pure Function
int add(int a, int b) {
return a + b;
}
void main() {
print(add(3, 5)); // Output: 8 (Always predictable)
}🚫 Impure Function Example (Modifies External State)
int counter = 0;
void increment() {
counter++;
} // ❌ Modifies global state (impure function)5️⃣ Immutability in Functional Programming
Immutability means variables and objects should not be modified after creation.
Example: Immutable Variables with final & const
final name = "Alice"; // Cannot be reassigned
const pi = 3.14; // Compile-time constantExample: Immutability in Data Structures (Using List.unmodifiable)
void main() {
final List<int> numbers = List.unmodifiable([1, 2, 3, 4]);
numbers.add(5); // ❌ This will throw an error
}6️⃣ Functional Collections: map(), where(), reduce(), fold()
Dart provides functional operations on lists like map, filter (where), reduce, and fold to process collections efficiently.
Example: Using map() for Transformation
void main() {
List<int> numbers = [1, 2, 3, 4];
List<int> doubled = numbers.map((num) => num * 2).toList();
print(doubled); // Output: [2, 4, 6, 8]
}Example: Using where() for Filtering
void main() {
List<int> numbers = [10, 20, 30, 40];
List<int> filtered = numbers.where((num) => num > 20).toList();
print(filtered); // Output: [30, 40]
}Example: Using reduce() to Accumulate Values
void main() {
List<int> numbers = [1, 2, 3, 4];
int sum = numbers.reduce((a, b) => a + b);
print(sum); // Output: 10
}Example: Using fold() with an Initial Value
void main() {
List<int> numbers = [1, 2, 3, 4];
int sum = numbers.fold(0, (prev, next) => prev + next);
print(sum); // Output: 10
}7️⃣ Currying in Dart (Partial Application)
Currying allows breaking down a function into multiple functions, each taking one parameter at a time.
Function add(int a) {
return (int b) => a + b;
}
void main() {
var addFive = add(5);
print(addFive(3)); // Output: 8
}8️⃣ Functional Reactive Programming (FRP) in Dart
Flutter’s state management solutions like Riverpod, Bloc, and RxDart are inspired by Functional Reactive Programming (FRP).
Get Punith S Uppar’s stories in your inbox
Join Medium for free to get updates from this writer.
Example using Stream (Reactive Programming):
Stream<int> countStream(int max) async* {
for (int i = 1; i <= max; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
void main() async {
await for (int value in countStream(5)) {
print(value); // Emits 1, 2, 3, 4, 5 with a delay
}
}🎯 Key Takeaways
✔️ Dart supports Functional Programming with higher-order functions, lambdas, and immutability.
✔️ Pure functions make code more predictable and testable.
✔️ List operations (map, where, reduce, fold) help process collections functionally.
✔️ Streams enable Functional Reactive Programming (FRP) in Dart.
By leveraging functional programming principles, you can write cleaner, more efficient, and maintainable Dart code.
📌 What’s Next?
Thinking of integrating functional programming in your Flutter app? Let me know in the comments! 😊









