Group Study (2024-2025)/Flutter

[Flutter] 1주차 스터디_함수형 프로그래밍 (Functional Programming)

siiion 2024. 9. 30. 22:23
Dart에서 자주 사용되는 함수형 프로그래밍 패턴과 그 장점

1. 형변환

- List, Map, Set을 변환하는 방법

1-1. List -> Map

- asMap(): 리스트의 각 요소를 key-value 쌍으로 매핑 (key는 리스트의 인덱스가 됨)

void main() {
  List<String> blackPink = ['로제', '지수', '리사', '제니'];
  print(blackPink.asMap()); // {0: 로제, 1: 지수, 2: 리사, 3: 제니}
}

1-2. List -> Set

- toSet() / Set.from(): 중복된 값을 자동으로 제거

void main() {
  List<String> blackPink = ['로제', '지수', '리사', '제니', '제니'];
  print(blackPink.toSet()); // {로제, 지수, 리사, 제니}
}

1-3. Iterable -> List

- .toList()

void main() {
  Map blackPinkMap = ['로제', '지수', '리사', '제니'].asMap();
  print(blackPinkMap.keys.toList());   // [0, 1, 2, 3]
  print(blackPinkMap.values.toList()); // [로제, 지수, 리사, 제니]
}

- keys와 values는 Iterable 형태로 반환 -> 리스트로 변환하기 위해 .toList() 사용


2. Mapping (맵핑 함수)

- map() 함수를 이용해 List, Map, Set의 각 요소를 변환하기
- 리스트의 각 요소에 대해 정의한 규칙을 적용한 새로운 컬렉션을 반환

2-1. List Mapping

void main() {
  List<String> blackPink = ['로제', '지수', '리사', '제니'];
  final newBlackPink = blackPink.map((x) => '블랙핑크 $x').toList();
  print(newBlackPink); // [블랙핑크 로제, 블랙핑크 지수, 블랙핑크 리사, 블랙핑크 제니]
}

2-2. Map Mapping

void main() {
  Map<String, String> harryPotter = {
    'Harry Potter': '해리 포터',
    'Ron Weasley': '론 위즐리',
    'Hermione Granger': '헤르미온느 그레인저'
  };
  
  final result = harryPotter.map((key, value) => MapEntry(
    'Harry Potter Character $key',
    '해리포터 캐릭터 $value'
  ));
}

2-3. Set Mapping

void main() {
  Set<String> blackPinkSet = {'로제', '지수', '리사', '제니'};
  final newSet = blackPinkSet.map((x) => '블랙핑크 $x').toSet();
  print(newSet); // {블랙핑크 로제, 블랙핑크 지수, 블랙핑크 제니, 블랙핑크 리사}
}

3. where 함수

- 조건에 맞는 요소들만 필터링 

void main() {
  List<Map<String, String>> people = [
    {'name': '로제', 'group': '블랙핑크'},
    {'name': '지수', 'group': '블랙핑크'},
    {'name': 'RM', 'group': 'BTS'},
    {'name': '뷔', 'group': 'BTS'}
  ];
  
  final blackPink = people.where((x) => x['group'] == '블랙핑크').toList();
  print(blackPink); // [{name: 로제, group: 블랙핑크}, {name: 지수, group: 블랙핑크}]
}

4. reduce 함수

- 리스트의 모든 요소를 하나의 값으로 축소
- 숫자의 합을 구하거나 문자열을 결합하는 데 사용

void main() {
  List<int> numbers = [1, 3, 5, 7, 9];
  final result = numbers.reduce((prev, next) => prev + next);
  print(result); // 25
}

- reduce는 항상 리스트의 타입과 동일한 타입을 반환


5. fold 함수

- fold() 함수는 reduce()와 유사하지만, 반환되는 값의 타입을 다르게 설정할 수 있다는 장점이 있음

void main() {
  List<String> words = ['안녕하세요 ', '저는 ', '코드팩토리입니다.'];
  final count = words.fold<int>(0, (prev, next) => prev + next.length);
  print(count); // 18
}

6. Cascading Operator 

- 여러 작업을 하나의 객체에 연속적으로 적용

void main() {
  List<int> even = [2, 4, 6, 8];
  List<int> odd = [1, 3, 5, 7];
  
  print([...even, ...odd]); // [2, 4, 6, 8, 1, 3, 5, 7]
}

함수형 프로그래밍(Functional Programming)의 특징과 주의할 점

특징

- 실행하는 대상과 완전히 다른 새로운 값을 생성
- 여러 함수를 체이닝(Chaining)하여 사용할 수 있음

주의할 점

- 너무 많은 체이닝은 코드의 가독성을 떨어뜨릴 수 있음


참고 자료

[코드팩토리] [입문] Dart 언어 4시간만에 완전정복 - Dart #3 Functional Programming 함수형 프로그래밍