Dart Functional Programming: Cheat Sheet Essentials
Introduction to Functional Programming in Dart
Functional programming (FP) is a programming paradigm that treats computation as the evaluation of mathematical functions. In Dart, functional programming provides powerful tools for writing clean, concise, and predictable code.

Key Functional Programming Concepts in Dart
1. First-Class and Higher-Order Functions
Dart treats functions as first-class citizens, allowing you to:
- Assign functions to variables
- Pass functions as arguments
- Return functions from other functions
Function as a variable (Dart)
void main()
{
// using -1
print("Sum ${add(10,89)}"); //outputs: Sum 99
// using - 2
var double = mutliplier(2);
print(double(5)); //outputs: 10
}
// function as a variable -1
Function add = (int a, int b) => a + b;
//Higher-order function -2
Function mutliplier(int factor) {
return (int number) => number * factor;
}
Output
Sum 99
10
2. Pure Functions (Dart)
Pure functions are deterministic and have no side effects:
- Always produce the same output for the same input
- Do not modify external state
- Do not depend on external state
Open DartPad and Write the following program:
void main()
{
print(calculateSquare(6)); // outputs: 36
}
// Pure function example
int calculateSquare(int number) {
return number * number;
}
3. Immutability
Dart supports immutability through final and const keywords:
void main()
{
// Immutable list
final List<int> numbers = [1, 2, 3];
// Compile-time constant
const PI = 3.14159;
}
//impossible: PI = 4.0;
//impossible: numbers = [5,6,7,7];
Remember: Constant variable can’t be re-assigned. The final variable ‘numbers’ can only set once.
4. Lambda Functions and Arrow Syntax
Dart provides concise syntax for creating anonymous functions:
void main()
{
// Lambda function
var squares = [1, 2, 3].map((number) => number * number);
print(squares);
}
Output
(1, 4, 9)
Functional Programming Techniques
Map, Filter, and Reduce
These higher-order functions are fundamental to functional programming:
void main() {
// Map: Transform list elements
var doubled = [1, 2, 3].map((x) => x * 2);
// Filter: Select elements based on condition
var evenNumbers = [1, 2, 3, 4].where((x) => x.isEven);
// Reduce: Combine list elements
var sum = [1, 2, 3].reduce((a, b) => a + b);
print(doubled); // outputs (2,4,6)
print(evenNumbers); // outputs (2,4)
print(sum); // outputs 6
}
Output
(2, 4, 6)
(2, 4)
6
Recursion
Functional programming often uses recursion instead of loops:
int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
void main() {
print(factorial(3)); // outputs : 6
}
Function Composition
Combining multiple functions to create new functions:
Function compose(Function f, Function g) {
return (x) => f(g(x));
}
void main() {
var double = (int x) => x * 2;
var square = (int x) => x * x;
var doubleAndSquare = compose(square, double);
print(doubleAndSquare(2)); //outputs 16
}
Advanced Functional Programming Concepts
Currying (Dart)
Breaking down functions with multiple arguments into a series of functions:
Function curriedAdd(int a) {
return (int b) => a + b;
}
void main() {
var add5 = curriedAdd(5);
print(add5(3)); // Outputs: 8
}
Lazy Evaluation
Dart supports lazy evaluation through iterables and generators:
Iterable<int> generateInfiniteSequence() sync* {
int i = 0;
while (true) {
yield i++;
}
}
void main() {
var count = 0;
for (var number in generateInfiniteSequence()) {
print(number);
count++;
if (count >= 50) break;
}
}
Output
0
1
2
3
.
49
generateInfiniteSequence() remains the same: This function still generates an infinite sequence of numbers.
count variable: We introduce a count variable to keep track of how many numbers we’ve printed.
for loop with a break condition:
- We iterate over the generateInfiniteSequence().
- Inside the loop, we print the number.
- We increment the count after each number is printed.
- The if (count >= 50) break; line checks if we’ve printed 50 numbers. If we have, the break statement exits the loop, stopping the printing.
Best Practices
- Prefer immutable data structures
- Use pure functions when possible
- Minimize state mutations
- Leverage higher-order functions
- Use pattern matching and switch expressions
Performance Considerations
While functional programming offers many benefits, be mindful of:
- Memory overhead of creating new objects
- Potential performance impact of recursive functions
- Garbage collection overhead
Verdict
Functional programming in Dart provides powerful tools for writing more predictable and maintainable code. By understanding and applying these concepts, you can write more elegant and efficient Dart applications.