복붙노트

[SCALA] 최적화 된 꼬리 재귀 함수를 보장하기 위해 스칼라 주석 무엇입니까?

SCALA

최적화 된 꼬리 재귀 함수를 보장하기 위해 스칼라 주석 무엇입니까?

나는 꼬리 재귀 함수를 최적화 컴파일러를 보장하기 @tailrec 주석이 있다고 생각합니다. 당신은 단지 선언 앞에 넣어합니까? 스칼라 스크립트 모드에서 사용되는 경우에도 사용할 수 있습니까 (사용 예를 들어 : REPL에서 부하 <파일>)?

해결법

  1. ==============================

    1.은 "꼬리 @tailrec 통화 및 트램폴린"블로그 게시물에서 :

    은 "꼬리 @tailrec 통화 및 트램폴린"블로그 게시물에서 :

    예:

    import scala.annotation.tailrec
    
    class Factorial2 {
      def factorial(n: Int): Int = {
        @tailrec def factorialAcc(acc: Int, n: Int): Int = {
          if (n <= 1) acc
          else factorialAcc(n * acc, n - 1)
        }
        factorialAcc(1, n)
      }
    }
    

    그리고 그것은 REPL (스칼라 REPL 팁과 트릭에서 예)에서 작동합니다 :

    C:\Prog\Scala\tests>scala
    Welcome to Scala version 2.8.0.RC5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_18).
    Type in expressions to have them evaluated.
    Type :help for more information.
    
    scala> import scala.annotation.tailrec
    import scala.annotation.tailrec
    
    scala> class Tails {
         | @tailrec def boom(x: Int): Int = {
         | if (x == 0) throw new Exception("boom!")
         | else boom(x-1)+ 1
         | }
         | @tailrec def bang(x: Int): Int = {
         | if (x == 0) throw new Exception("bang!")
         | else bang(x-1)
         | }
         | }
    <console>:9: error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position
           @tailrec def boom(x: Int): Int = {
                        ^
    <console>:13: error: could not optimize @tailrec annotated method: it is neither private nor final so can be overridden
           @tailrec def bang(x: Int): Int = {
                        ^
    
  2. ==============================

    2.스칼라 컴파일러는 자동으로 진정으로 꼬리 재귀 방법을 최적화합니다. 당신이 꼬리 재귀 @tailrec 주석으로 판단하는 방법에 주석을 경우이 방법은 실제로 꼬리 재귀되지 않는 경우, 컴파일러는 경고합니다. 이 모두는 방법은 현재 최적화 할 수 있는지 확인하고이를 수정으로는 최적화 할 유지하려면 @tailrec 주석 좋은 생각합니다.

    스칼라 컴파일러는 자동으로 진정으로 꼬리 재귀 방법을 최적화합니다. 당신이 꼬리 재귀 @tailrec 주석으로 판단하는 방법에 주석을 경우이 방법은 실제로 꼬리 재귀되지 않는 경우, 컴파일러는 경고합니다. 이 모두는 방법은 현재 최적화 할 수 있는지 확인하고이를 수정으로는 최적화 할 유지하려면 @tailrec 주석 좋은 생각합니다.

    스칼라가 오버라이드 (override) 할 수있는 경우 꼬리 재귀하는 방법을 고려하지 않습니다. 따라서, 상기 방법은 하나 (a 클래스 또는 형질 대조적으로) 객체에 대한 최종 전용이거나 다른 방법으로 내부 최적화한다.

  3. ==============================

    3.주석은 scala.annotation.tailrec입니다. 이 경우 어떻게 방법이 꼬리를 호출 최적화 할 수없는 경우 컴파일러 오류를 트리거 :

    주석은 scala.annotation.tailrec입니다. 이 경우 어떻게 방법이 꼬리를 호출 최적화 할 수없는 경우 컴파일러 오류를 트리거 :

    그것은 단지 메소드 정의에서 DEF 앞에 위치합니다. 그것은 REPL에서 작동합니다.

    여기에서 우리는 주석을 가져오고 @tailrec 등의 방법을 표시하려고합니다.

    scala> import annotation.tailrec
    import annotation.tailrec
    
    scala> @tailrec def length(as: List[_]): Int = as match {  
         |   case Nil => 0
         |   case head :: tail => 1 + length(tail)
         | }
    <console>:7: error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position
           @tailrec def length(as: List[_]): Int = as match { 
                        ^
    

    아차! 마지막 호출은 1입니다. + (),하지 길이 ()! 의이 방법을 재구성 보자 :

    scala> def length(as: List[_]): Int = {                                
         |   @tailrec def length0(as: List[_], tally: Int = 0): Int = as match {
         |     case Nil          => tally                                       
         |     case head :: tail => length0(tail, tally + 1)                    
         |   }                                                                  
         |   length0(as)
         | }
    length: (as: List[_])Int
    

    이 다른 방법의 범위에 정의되어 있으므로 자동 사적 length0 유의.

  4. from https://stackoverflow.com/questions/3114142/what-is-the-scala-annotation-to-ensure-a-tail-recursive-function-is-optimized by cc-by-sa and MIT license