SSAFY-Book-Study / modern-java-in-action

모던 자바 인 액션 북스터디입니다.
1 stars 10 forks source link

6 Weeks - [재귀와 꼬리 호출 최적화] #83

Open DeveloperYard opened 1 year ago

DeveloperYard commented 1 year ago

문제

재귀와 꼬리 호출의 차이점과 꼬리 호출은 어떻게 최적화가 되는 걸까요?

contents - 세부 내용

예전에 찾아본 적이 있었는데 책에는 자세한 내용이 없는 것 같아 이슈로 삼았습니다.

참고

582p

skagmltn7 commented 1 year ago

재귀

static int fact(int n)
{
    if(n < 2) return 1;
    return n * fact(n-1);
}

/*
(fact 3) 
(* 3 (fact 2)) 
(* 3 (* 2 (fact 1)))
(* 3 (* 2 (* 1 (fact 0)))) // 여기까지 스택쌓임
(* 3 (* 2 (* 1 1))) // 스택빠지기 시작
(* 3 (* 2 1))
(* 3 2)
6
*/

Untitled

꼬리호출


static int fact(int n){
    return fact_tail(n, 1);
}

static int fact_tail(int n, int total){
    if(n < 1) return total;
    return fact_tail(n - 1, n * total);
}

/*
(fact 3)
(fact_tail 3 1)
(fact_tail 2 3)
(fact_tail 1 6)
(fact_tail 0 6)
6
*/

Untitled

꼬리 호출의 최적화

스칼라, 코틀린 등의 경우 다음과 같이 컴파일러가 자체적으로 꼬리 재귀 최적화를 한다.

// 이코드를
static int fact_tail(int n, int total){
    if(n < 1) return total;
    return fact_tail(n - 1, n * total);
} 

// while 반복문으로 자동 최적화하여 바이트코드로 변환함
static int fact_tail(int n, int total){
    while(n != 1) {
         int var = total * n;
         --n;
         total = var;
      }
  return total;
}

그러나 자바에서는 스택 프레임의 수에 의존하는 몇몇 jdk클래스가 존재하는데 프레임을 변경했을 때 오류가 발생할 수 있기 때문에 자동 꼬리 호출 최적화를 지원하지 않는다. 자바8의 람다식과 함수형 인터페이스를 사용하면 내부반복으로 직접 꼬리호출을 최적화할 수 있다.

출처

람다식과 함수형 인터페이스를 이용한 꼬리호출 최적화

https://joooing.tistory.com stackoverflow