1. 고차 함수 (Higher-order Functions)
고차 함수는 다른 함수를 인자로 받거나, 함수를 반환하는 함수임
Dart에서는 고차 함수를 사용하여 코드를 더욱 유연하고 재사용 가능하게 만들 수 있음
1.1 함수 전달
void executeFunction(String message, Function(String) callback) {
callback(message);
}
void printMessage(String message) {
print(message);
}
void main() {
executeFunction("Hello, Dart!", printMessage); // Hello, Dart!
}
1.2 함수 반환
Function makeMultiplier(int multiplier) {
return (int value) => value * multiplier;
}
void main() {
var triple = makeMultiplier(3);
print(triple(4)); // 12
}
함수를 반환하여 재사용 가능한
예를 들어 API에서 특정한 값이 들어올 때, 변환하여 사용하거나
계산하여 사용해야 할때 유용하며
재사용이 가능하기 때문에 중복 코드를 줄일 수 있음
2. 익명 함수 (Anonymous Functions)
간단한 작업을 위해 함수 본문을 인라인으로 정의함
불필요한 함수 정의를 줄임
2.1 기본 사용법
void main() {
var numbers = [1, 2, 3, 4];
numbers.forEach((number) {
print(number * 2); // 2, 4, 6, 8
});
}
2.2 축약 표현 (Fat Arrow)
한 줄로 표현할 수 있는 익명 함수는 화살표(=>
)로 축약하여 사용
void main() {
var numbers = [1, 2, 3, 4];
numbers.forEach((number) => print(number * 2));
}
3. 클로저 (Closures)
클로저는 자신이 정의된 스코프 외부의 변수를 참조할 수 있는 함수입니다.
Dart의 클로저는 변수를 캡처하여, 외부 함수의 실행이 끝난 후에도 해당 변수에 접근 가능
Function makeCounter() {
int count = 0;
return () {
count++;
return count;
};
}
void main() {
var counter = makeCounter();
print(counter()); // 1
print(counter()); // 2
print(counter()); // 3
}
4. 컬렉션 조작 함수
List
, Map
, Set
의 사용
4.1 map
map
은 컬렉션의 각 요소를 변환하여 새로운 컬렉션을 반환
void main() {
var numbers = [1, 2, 3];
var doubled = numbers.map((n) => n * 2).toList();
print(doubled); // [2, 4, 6]
}
4.2 where
where
는 조건에 맞는 요소만 필터링 됨
void main() {
var numbers = [1, 2, 3, 4, 5];
var evenNumbers = numbers.where((n) => n.isEven).toList();
print(evenNumbers); // [2, 4]
}
4.3 reduce
reduce
는 컬렉션을 단일 값으로 축약 되어 값을 반환
void main() {
var numbers = [1, 2, 3, 4];
var sum = numbers.reduce((a, b) => a + b);
print(sum); // 10
}
값을 모두 더하거나 뺄 때 특히 유용함
4.4 fold
fold
는 reduce
와 유사하지만, 초기 값을 제공할 수 있음
void main() {
var numbers = [1, 2, 3, 4];
var result = numbers.fold(10, (a, b) => a +b);
print(result); // 20
}
즉 초기값 + reduce 함수 실행 되는 형태
5. Generator Functions
Dart에서는 sync*
와 async*
키워드를 사용해 제너레이터 함수를 정의 가능
데이터를 한 번에 반환하지 않고, 필요할 때마다 생성되어 메모리에 유리한 편
5.1 sync*
(동기 제너레이터)
Iterable<int> generateNumbers(int count) sync* {
for (int i = 1; i <= count; i++) {
yield i;
}
}
void main() {
var numbers = generateNumbers(5);
print(numbers.toList()); // [1, 2, 3, 4, 5]
}
5.2 async*
(비동기 제너레이터)
Stream<int> generateNumbers(int n) async* {
for (int i = 1; i <= n; i++) {
await Future.delayed(Duration(milliseconds: 500));
yield i;
}
}
void main() async {
await for (var number in generateNumbers(3)) {
print(number); // 1, 2, 3
}
}
0.5초 마다 1, 2, 3 이 출력됨
스트림 형식이니, APi에서 받아오는 경우 해당 함수를 섞어 쓰면
UI 적 측면에서도 도움이됨
6. 커링 (Currying)
커링은 함수의 일부 인자를 고정하여 새로운 함수를 생성하는 패턴
Function add(int a) {
return (int b) => a + b;
}
void main() {
var addFive = add(5);
print(addFive(10)); // 15
}
추가 포스팅 참조
7. 컴포지션 (Composition)
여러 함수를 결합하여 새로운 함수 생성
Dart에서는 이를 클로저와 함께 구현 가능
Function compose(Function f, Function g) {
return (x) => f(g(x));
}
void main() {
var double = (int x) => x * 2;
var increment = (int x) => x + 1;
var doubleThenIncrement = compose(increment, double);
print(doubleThenIncrement(3)); // 7
}
추가 포스팅 참조
고차 함수, 클로저, 컬렉션 조작 메서드, 그리고 제너레이터 등을 적절히 활용하면
더욱 읽기 쉽고 유지보수하기 쉬운 코드를 작성 할 수 있음
다만, 과하게 사용하면 오히려 읽기 어려운 코드가 될 수 있기 때문에
적절히 사용하는 것을 추천
'develop > Flutter' 카테고리의 다른 글
[flutter] 겹치는 프로그래스바 - 값이 여러개인 프로그래스바 만들기 (0) | 2024.11.26 |
---|---|
Dart에서 Currying 사용하기 - 커링 함수사용하여 코드 질 높이기 (0) | 2024.11.18 |
Dart에서 `toList()`와 `toMap()` 사용법, 응용 하기 (0) | 2024.11.12 |
Dart에서 맵(map) 다루기 (0) | 2024.11.11 |
Dart에서 리스트(List) 다루기 (0) | 2024.11.10 |