선수로 산다, 때론 좋은 코치로

[함수형 프로그래밍] 코드로 보는 함수형 프로그래밍의 차이 본문

개발 관련/개발 일반

[함수형 프로그래밍] 코드로 보는 함수형 프로그래밍의 차이

godsman 2016. 11. 4. 19:33

[함수형 프로그래밍] 코드로 보는 함수형 프로그래밍의 차이

1부터 10까지의 숫자 중에서, 짝수이면서, 2를 곱한 값 중에서, 5보다 큰 최초의 값은 얼마인가?

일반적인 절차형 프로그램으로 개발하면, 루프를 돌면서, 순서대로 계산한다.

public static void main(String[] args)
{
  List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
 
  for (int number : numbers) {
   System.out.println("for-each(%2): " + number);   
   if ((number % 2) == 0) {
    System.out.println("for-each(*2): " + (number * 2));   
    if ((number * 2) > 5) {
     System.out.println("for-each(>5): " + (number * 2));
     break;
    }
   }
  }
}

결과는 쉽게 예상할 수 있다.

for-each(%2): 1
for-each(%2): 2
for-each(*2): 4
for-each(%2): 3
for-each(%2): 4
for-each(*2): 8
for-each(>5): 8

이것을 객체지향 프로그램으로 변경하면 다음과 같다.

1부터 10까지의 숫자 리스트에서 짝수 리스트를 구한다. 짝수 리스트에서 2의 배수 리스트를 구한다. 2의 배수 리스트에서 5보다 큰 최초의 숫자를 구한다. 함수형 프로그래밍에서 사용하기 위해서 함

public static void main(String[] args)
{
  List<Integer> l1 = new ArrayList<Integer>();
  for (int n : numbers) {
   if (isEven(n)) l1.add(n);
  }
  
  List<Integer> l2 = new ArrayList<Integer>();
  for (int n : l1) {
   l2.add(doubleIt(n));
  }
  
  List<Integer> l3 = new ArrayList<Integer>();
  for (int n : l2) {
   if (isGreaterThan5(n)) l3.add(n);
  }
  
  System.out.println(l3.get(0));

public static boolean isEven(int number) {
  System.out.println("isEven: " + number);
  return number % 2 == 0;
 }
 
 public static int doubleIt(int number) {
  System.out.println("doubleIt: " + number);
  return number * 2;
 }
 
 public static boolean isGreaterThan5(int number) {
  System.out.println("isGreaterThan5: " + number);
  return number > 5;
 }

결과는 다음과 같다. 예상대로 결과와 관계없이 주어진 숫자의 리스트를 모두 계산해서 구해 놓는다.

isEven: 1
isEven: 2
isEven: 3
isEven: 4
isEven: 5
isEven: 6
isEven: 7
isEven: 8
isEven: 9
isEven: 10
doubleIt: 2
doubleIt: 4
doubleIt: 6
doubleIt: 8
doubleIt: 10
isGreaterThan5: 4
isGreaterThan5: 8
isGreaterThan5: 12
isGreaterThan5: 16
isGreaterThan5: 20
8 

함수형 프로그램에서는 filter와 map, findFirst 함수를 연결하여 호출하는 방법을 사용한다. 이 때는 어떻게 동작할까?

public static void main(String[] args)
{
  System.out.println(

    numbers.stream()
     .filter(WhyLambda::isEven)
     .map(WhyLambda::doubleIt)
     .filter(WhyLambda::isGreaterThan5)
     .findFirst()
  );
 }
 public static boolean isEven(int number) {
  System.out.println("isEven: " + number);
  return number % 2 == 0;
 }
 
 public static int doubleIt(int number) {
  System.out.println("doubleIt: " + number);
  return number * 2;
 }
 
 public static boolean isGreaterThan5(int number) {
  System.out.println("isGreaterThan5: " + number);
  return number > 5;
 }

결과는 다음과 같다. 지연실행의 결과로 필요한 경우만 계산을 하고 값을 구한 후에는 멈추었다. 절차형 프로그램의 수행방법과 비슷하다.

isEven: 1
isEven: 2
doubleIt: 2
isGreaterThan5: 4
isEven: 3
isEven: 4
isGreaterThan5: 8
Optional[8]

Comments