Scala

Scala에서의 map/flatmap, for

partner_jun 2017. 2. 11. 11:09

함수형 프로그래밍의 주요 함수 중 하나인 map은 n개의 요소 각각에 함수를 적용한 결과를 만들어내는 함수이다. 많은 문제를 접하다 보면 자연스레 for보다 map을 선호하게 되는데 문제에 따라 for문을 사용하는 것이 더 간결한 코드를 만들어 낼 수 있었다. 구구단의 예를 들어 보자.


원하는 결과가 1단부터 9단까지 결과의 리스트라고 하자. 이 때 flatMap함수를 사용한다면 이렇게 쓸 수 있다.

val range = 1 to 9

val result = range.flatMap{i =>
range.flatMap{j =>
List(i * j)
}
}


1) 2의 배수 단의 결과만을 얻고 싶다고 해 보자.

val result = range.filter(_ % 2 == 0).flatMap{i =>
range.flatMap{j =>
List(i * j)
}
} // Vector(2, 4, 6, 8, 10, 12, 14, 16, ..., 72)


2) 각 단의 홀수의 곱을 얻고 싶다고 해 보자.

val result = range.filter(_ % 2 == 0).flatMap{i =>
range.filterNot(_ % 2 == 0).flatMap{j =>
List(i * j)
}
} // Vector(2, 6, 10, 14, 18, 4, 12, 20, ...72)


결과는 문제없지만 점점 코드가 복잡해지고 브레이슬릿이 많아진다. _를 이용해 단축 시켰음에도 길다. 더 복잡한 문제라면 아마 작성한 자신 뿐 아니라 코드를 보는 다른 사람도 불편함을 느끼게 될 것이다.


2)와 같은 조건에서 for문을 사용한다면

val result = for{i <- range if i % 2 == 0
j <- range if j % 2 != 0} yield i * j
// Vector(2, 6, 10, 14, 18, 4, 12, 20, ...72)

이렇게 더 직관적인 코드로 만들 수 있다. 


하지만 for 구문이 만능인 것은 아니다. 위와 같은 문제에서 결과를 각 단의 리스트로 만들고 싶을 때는 어떨까? map/flatMap을 이용한것과 별 차이가 없는, 혹은 더 복잡한 코드가 될 것이다. 


나는 사실 지금까지 모든 경우에 map과 flatMap 함수를 사용했다. 하지만 Ninty-Nine Scala Problems 중 93번 Arithmetic Puzzle같은 문제에서는 오히려 더 복잡하고 이해하기 힘든 구문이 되었다. 그래서 for문을 사용해 보니 훨씬 만족스러운 결과를 얻었다. 둘 모두 아주 강력한, 추상화된 함수지만 장단점을 생각하고 적절한 곳에 사용해야 더 큰 도움이 될 것이라고 생각한다.