2015-11-06 61 views
1

scala的@tailrec註釋是否支持Option.fold方法?Scala @tailrec與摺疊

@tailrec 
def test(a: Int): Int = 
    if (a > 10) 
    Option(true).fold(test(a - 1))(_ => test(a - 2)) 
    else 
    -1 

該代碼產生錯誤:

Could not optimize @tailrec annotated method test: it contains a recursive call not in tail position

這個問題可以通過模式匹配,但我覺得fold看起來清爽多瞭解決。

+0

什麼在這種情況下使用摺疊點?你的方法總是返回-1。你根本不需要遞歸:) – Rumoku

+0

@ Mr.V。這僅僅是一個例子。 – mopdobopot

回答

7

當你想在Scala中編寫一個尾遞歸函數時,你對尾遞歸函數的調用需要處於最後位置(因此尾調用遞歸)。

在你的情況下,Option.fold是最後一個,Scala編譯器不能發現fold的結果總是調用test

您可以使用TailCals,編寫使用fold一個尾遞歸函數:

import scala.util.control.TailCalls._ 

def test(a: Int): TailRec[Int] = 
    if (a > 10) tailcall(Option(true).fold(test(a - 1))(_ => test(a - 2))) 
    else done(-1) 

test(11).result // -1 

是,如果你發現使用TailRec更簡潔比使用模式匹配爲您deside:

def test(a: Int): Int = 
    if (a > 10) Option(true) match { 
    case Some(_) => test(a - 2) 
    case None => test(a - 1) 
    } 
    else -1 
+0

謝謝!對於多餘的封裝器'tailcall',它看起來不像聲明式匹配。 – mopdobopot