함수형 사고로 패러다임을 바꾸면 더 적은 노력으로 더 많은 일을 할 수 있게 됩니다. 함수형 프로그래밍의 많은 구조들이 그렇습니다. 절차형 언어에서 볼 수 있는 문제들을 구현할 때 짜증 나던 것들을 제거해 줍니다.
메모이제이션
메모이 제이션은 연속해서 사용되는 연산값을 함수 레벨에서 캐시하는 것을 말합니다. 메모이제이션은 캐싱을 이용하여 처리합니다. 캐싱을 이용하기 위해서는 주어진 매개변수의 값만을 이용하고, 외부 데이터에 영향을 받지 않는 순수 함수를 이용해야 합니다.
다음은 스칼라에서 피보나치 함수를 캐싱을 이용하여 구현한 예제입니다.
object memoizeSample extends App { | |
// 처리 시간 출력 | |
import java.util.concurrent.TimeUnit.NANOSECONDS | |
def time[T](f: => T): T = { | |
val start = System.nanoTime() | |
val ret = f | |
val end = System.nanoTime() | |
println(s"Time taken: ${NANOSECONDS.toNanos(end - start)} nonos") | |
ret | |
} | |
// Map에 함수데이터 캐싱 | |
def memoize[A, B](f: A => B) = new (A => B) { | |
val cache = scala.collection.mutable.Map[A, B]() | |
def apply(x: A): B = cache.getOrElseUpdate(x, f(x)) | |
} | |
// 피보나치 함수 | |
def fibo(x: Int): Int = { | |
if (x <= 2) | |
1 | |
else | |
fibo(x - 2) + fibo(x - 1) | |
} | |
// 캐싱 | |
def memoFibo = memoize(fibo) | |
for(x <- 1 to 10) | |
println(time(memoFibo(30))) | |
} |
처리 결과를 보면 다음처럼 2번째 처리부터 처리시간이 단축되는 것을 볼 수 있습니다.
Time taken: 9275948 ms
832040
Time taken: 2802375 ms
832040
Time taken: 2451631 ms
832040
Time taken: 2423518 ms
832040
Time taken: 2364615 ms
832040
Time taken: 3462807 ms
832040
Time taken: 2439583 ms
832040
Time taken: 2352566 ms
832040
Time taken: 2440029 ms
832040
Time taken: 2868864 ms
832040
게으름(Lazy Evalution)
표현의 평가를 가능한 최대로 늦추는 기법인 게으른 평가는 함수형 프로그래밍에서 많이 볼 수 있는 기능입니다. 게으른 평가를 이용하면 한번에 모든 데이터를 생성하지 않고 필요한 시간에 하나씩 생성합니다. 이를 통해 메모리상의 이점을 가질 수 있고 빠른 속도로 데이터를 처리할 수 있습니다.
'개념 > 함수형사고' 카테고리의 다른 글
[함수형 사고] 6장 전진하라 (0) | 2019.03.13 |
---|---|
[함수형 사고] 5장 진화하라 (0) | 2019.03.12 |
[함수형 사고] 3장 양도하라 (0) | 2019.03.08 |
[함수형 사고] 2장 전환 (0) | 2019.03.05 |
[함수형 사고] 1장 왜? (1) | 2019.03.04 |