141 lines
3.0 KiB
Markdown
141 lines
3.0 KiB
Markdown
# Functional Programming Concepts in Dart: A Comprehensive Guide
|
|
|
|
While Dart is primarily an object-oriented language, it also supports many functional programming concepts. This guide covers key functional programming features in Dart.
|
|
|
|
## 1. Higher-Order Functions
|
|
|
|
Higher-order functions are functions that can take other functions as parameters or return functions.
|
|
|
|
### Example:
|
|
|
|
```dart
|
|
void main() {
|
|
var numbers = [1, 2, 3, 4, 5];
|
|
|
|
// Using a higher-order function (map)
|
|
var doubled = numbers.map((n) => n * 2);
|
|
print(doubled); // (2, 4, 6, 8, 10)
|
|
|
|
// Creating a higher-order function
|
|
Function multiplyBy(int factor) {
|
|
return (int number) => number * factor;
|
|
}
|
|
|
|
var tripler = multiplyBy(3);
|
|
print(tripler(4)); // 12
|
|
}
|
|
```
|
|
|
|
## 2. Closures
|
|
|
|
Closures are functions that have access to variables in their lexical scope, even when the function is used outside of its original scope.
|
|
|
|
### Example:
|
|
|
|
```dart
|
|
Function counter() {
|
|
int count = 0;
|
|
return () {
|
|
count++;
|
|
return count;
|
|
};
|
|
}
|
|
|
|
void main() {
|
|
var increment = counter();
|
|
print(increment()); // 1
|
|
print(increment()); // 2
|
|
print(increment()); // 3
|
|
}
|
|
```
|
|
|
|
## 3. Pure Functions
|
|
|
|
Pure functions always produce the same output for the same input and have no side effects.
|
|
|
|
### Example:
|
|
|
|
```dart
|
|
// Pure function
|
|
int add(int a, int b) {
|
|
return a + b;
|
|
}
|
|
|
|
// Impure function (has side effect)
|
|
int currentCount = 0;
|
|
int incrementAndAdd(int value) {
|
|
currentCount++;
|
|
return currentCount + value;
|
|
}
|
|
|
|
void main() {
|
|
print(add(3, 4)); // Always 7
|
|
print(incrementAndAdd(3)); // 4
|
|
print(incrementAndAdd(3)); // 5
|
|
}
|
|
```
|
|
|
|
## 4. Immutability
|
|
|
|
Immutability involves working with unchangeable data. Dart supports this through `final` and `const` keywords.
|
|
|
|
### Example:
|
|
|
|
```dart
|
|
void main() {
|
|
final list = [1, 2, 3];
|
|
// list = [4, 5, 6]; // Error: Can't assign to final variable
|
|
list.add(4); // OK, but modifies the list
|
|
|
|
const constList = [1, 2, 3];
|
|
// constList.add(4); // Error: Can't modify a const list
|
|
|
|
// Creating a new list instead of modifying
|
|
final newList = [...list, 5];
|
|
print(newList); // [1, 2, 3, 4, 5]
|
|
}
|
|
```
|
|
|
|
## 5. Recursion
|
|
|
|
Recursion is a technique where a function calls itself to solve a problem.
|
|
|
|
### Example:
|
|
|
|
```dart
|
|
int factorial(int n) {
|
|
if (n <= 1) return 1;
|
|
return n * factorial(n - 1);
|
|
}
|
|
|
|
void main() {
|
|
print(factorial(5)); // 120
|
|
}
|
|
```
|
|
|
|
## 6. Function Composition
|
|
|
|
Function composition involves creating a new function by combining other functions.
|
|
|
|
### Example:
|
|
|
|
```dart
|
|
Function compose(Function f, Function g) {
|
|
return (x) => f(g(x));
|
|
}
|
|
|
|
int square(int x) => x * x;
|
|
int addOne(int x) => x + 1;
|
|
|
|
void main() {
|
|
var squareThenAddOne = compose(addOne, square);
|
|
var addOneThenSquare = compose(square, addOne);
|
|
|
|
print(squareThenAddOne(3)); // 10
|
|
print(addOneThenSquare(3)); // 16
|
|
}
|
|
```
|
|
|
|
## Conclusion
|
|
|
|
While Dart is not a purely functional language, it provides many features that support functional programming paradigms. Understanding and using these concepts can lead to more concise, maintainable, and testable code. |