반응형
꼬리 재귀 함수를 최적화하기위한 Scala 주석은 무엇입니까?
@tailrec
가 꼬리 재귀 컴파일러 함수를 최적화 할 수 있도록 주석 이 있다고 생각 합니다. 선언문 앞에 놓으시나요? 스칼라가 스크립팅 모드 (예 :load <file>
: REPL 에서 사용)에서 사용되는 경우에도 작동합니까 ?
- Scala 2.8에서는 새로운 주석
@tailrec
을 사용하여 최적화 된 방법에 대한 정보를 얻을 수도 있습니다 .
이 주석을 사용하면 컴파일러가 최적화 할 특정 방법을 표시 할 수 있습니다.
그런 다음 컴파일러에 의해 최적화되지 않은 경우 경고가 표시됩니다.- Scala 2.7 또는 이전 버전에서는 메소드가 최적화 여부를 확인하기 위해 수동 테스트 또는 바이트 코드를 검사해야합니다.
예 :
@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에서 작동합니다 ( Scala 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 = {
^
Scala 컴파일러는 진정한 꼬리 재귀 방법을 자동으로 최적화합니다. 꼬리 재귀 적이라고 생각되는 메서드에 주석을 달면 @tailrec
컴파일러는 메서드가 실제로 꼬리 재귀 적이 지 않은지 경고합니다. 이렇게하면 메소드 @tailrec
가 현재 최적화 가능하고 수정 될 때도 최적화 가능한 상태로 유지되는 주석이 좋은 아이디어가됩니다.
Scala는 재정의 할 수있는 경우 방법을 꼬리 재귀로 말할 것도 없습니다. 따라서 메서드는 개인, 최종, 객체 (클래스 또는 특성과 반대) 또는 최적화 할 다른 메서드 내부에 있어야합니다.
주석은입니다 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.+()
하지 length()
! 방법을 내부 해 보겠습니다.
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
이 다른 방법의 범위에 정의되어 있기 때문에 자동으로 비공개입니다.
반응형
'IT' 카테고리의 다른 글
jquery에서 첫 번째 수준 요소 만 선택 (0) | 2020.09.03 |
---|---|
URL 변수의 슬래시 (0) | 2020.09.03 |
목록 색인? (0) | 2020.09.03 |
배치 파일을 시작 / 호출 할 때 인수가 정의되어 있습니까? (0) | 2020.09.03 |
jQuery : 부모의 특정 구매 방법? (0) | 2020.09.03 |