2017-12-05 4 views
1

를 비교하는 이유는이 꼬리 재귀입니다 myList 매우 긴꼬리 재귀 : 이가지 경우

def navigate(myList : List[Int]) : (Int, List[Int]) = { 
    navigate(0, 0, myList) 
} 

def navigate(step: Int, offset: Int, myList: List[Int]): (Int, scala.List[Int]) = { 
    if //some test and exit condition, then a definition of jump 
    else navigate(step + 1, offset + jump, myList) 
} 

경우, 첫 번째 경우는 어떤 문제를 제공하지 않습니다, 경우 두 번째 것은 StackOverflowError입니다.

또한 컴파일러가 재귀가 스택을 증가시키지 않도록 컴파일해야한다고 말하는 방법이 있습니까? 방법에 대한

위해
+0

https://anadea.info/blog/tail-recursion-in-scala가 유용 할 수 있습니다. 그 중 무엇을 얻었는지는'@ tailrec'을 사용하여 주석을 달 수 있으며 컴파일러에서 경고를받습니다 if 최적화되지 않았습니다. – ameer

+0

또한 https://stackoverflow.com/questions/3114142/what-is-the-scala-annotation-to-ensure-a-tail-recursive-function-is-optimized는 다소 자세한 공지가있는 것처럼 보입니다. 최적화되지 않은 이유. – ameer

+0

@ameer 이미 시도했지만 컴파일 오류가 있습니다. "@tailrec '이 주석 처리 된 메서드는 내 경우에는 좋을 수도 있지만 일반적으로 그렇지 않을 수도 있습니다. – marco

답변

4

꼬리 재귀 최적화를위한 자격하기 위해서는해야합니다

  • 이 꼬리 재귀 (! 대만족)
  • return
  • 사용하지 final

두 예제 모두 # 1과 # 2를 따르지만 첫 번째 예제 만 # 3을 준수합니다 (로컬 메소드는 암시 적으로 최종적입니다).

final 수없는 경우 방법은 꼬리 재귀없는 이유는 "꼬리 재귀가" "꼬리 호출 자체"를 의미하지만,이 방법은 가상 경우에, 당신은 그 꼬리 여부을 알 수 없다 -calls 자체 또는 재정의 된 버전입니다. 컴파일 시간에 메소드가 재정의되었는지 여부를 파악하려면 클래스 계층 구조 분석이 필요합니다. Half Problem을 해결하는 것과 동등한 것으로 알려져 있습니다 ... IOW는 불가능합니다.

또한 컴파일러가 재귀가 스택을 증가시키지 않도록 컴파일해야한다고 말하는 방법이 있습니까?

아니요. 꼬리 재귀 최적화를 설정하거나 해제 할 수는 없습니다. tail-recursive (스칼라 언어 사양의 "tail-recursive"정의에 따라) 메서드는 항상으로 최적화되어 있습니다. 이 작업을 수행하지 않는 스칼라 구현은 스칼라 언어 사양을 위반 한 것입니다. 이

이다, 그러나,이 주석과 주석이 방법은 꼬리 재귀의 SLS의 정의에 부합하지 않는 경우 컴파일러 오류가 발생합니다 것을 보장 scala.annotation.tailrec 주석.

+0

감사합니다! "당신이 스스로를 꼬리 부르는지 아니면 스스로 재정의 한 버전인지를 알 수 없습니다."고맙습니다. 이것은 제가 놓친 것입니다. – marco