2011-03-17 3 views
7

검사 :왜이 꼬리가 재귀입니까? 이 스칼라 코드 밖으로

def rec(n: Int) { 
    if (n > 1) { 
    val d = n/2 
    rec(d) 
// if (d > 1) // abort loop 
     rec(n/d) 
    } 
} 

이 코드는 무한 루프가 발생합니다. 꼬리 재귀 최적화 때문에 StackOverflowError를 얻지 못했습니다. 이 방법은 그러므로 나는 꼬리 호출 위치를 이해하지 못하는 자신을 호출하는 루프의 마지막 줄에

public void rec(int n) 
{ 
    int d; 
    for(; n > 1; n /= d) 
    { 
     int i = n; 
     d = i/2; 
     rec(d); 
    } 
} 

: JAD와 디 컴파일

나는이 자바 코드를 얻었다. 이것을 설명 할 수있는 사람은 누구입니까?

+0

도움이 될 것입니다. 1.http : //www.cs.wayne.edu/~artem/main/teaching/csc3200ss2006/slides/recursion/types.html 2.http : //stackoverflow.com/questions/ 105834/does-the-jvm-prevent-tail-call-optimizations –

답변

9

rec(d)의 경우 꼬리 전화가 없습니다. log2(N) 호출 이후에 rec(N) (여기서 N > 1) 스택이 더 이상 성장하지 않으면 (이후 n은 영원히 2 또는 3이고 d은 1이기 때문에) 호출이 더 이상 성장하지 않습니다. 그 후에는 매번 즉시 반환되는 내부의 rec(1) 호출과 함께 무한 루프입니다. 그래서 스택 오버 플로우가 발생하지 않습니다.

3

메서드의 재귀 적 형식에서는 두 가지 재귀 호출이 있습니다. StackOverflowError은 마지막 것 때문에 발생합니다.

꼬리 재귀 최적화로 인해 마지막 호출이 루프로 바뀌므로 (첫 번째 호출이 반복적으로 유지되는 동안) 무한 반복 대신 무한 루프가 발생하고 StackOverflowError이 발생하지 않습니다.