我知道在使用 Loops 時,可變性會出現并且難以追蹤。但是僅僅因為在 Scala 中遞回被認為是回圈的可變性嗎?
另外我知道尾遞回不會添加到您的呼叫堆疊中,但并非所有問題都可以使用尾遞回來解決,對嗎?使用基于累加器的方法如何,這似乎也足以避免堆疊溢位情況?尾遞回和基于累加器的遞回方法之間的性能如何?
簡而言之,我有兩個問題:
- 由于尾遞回不能用于解決所有回圈問題(或者可以嗎?)回圈不是更好還是某些特定用例的唯一解決方案?
- 尾遞回和基于累加器的遞回有什么區別,根據空間復雜度和呼叫堆疊占用,哪個性能更好?
編輯1:
在基于累加器的遞回(階乘函式)中轉換的非尾遞回函式(使用中間尾遞回函式)的示例:
不帶蓄能器:
def factorial(n: Int): Int = {
if (n <= 1) 1
else n * factorial(n - 1)
}
帶蓄能器:
def tailRecFactorial(n: Int): BigInt = {
@tailrec
def factorialHelper(x: Int, accumulator: BigInt): BigInt = {
if (x <= 1) accumulator
else factorialHelper(x - 1, x * accumulator)
}
factorialHelper(n, 1)
}
uj5u.com熱心網友回復:
Scala 是一種函式式語言,函式式代碼通常被認為比非函式式代碼更好。反對意見while是它依賴于在迭代期間更改的值,因此無法正常作業。
回答具體問題:
任何回圈都可以表示為純尾遞回函式,但它可能會非常麻煩地確定將什么狀態傳遞給遞回呼叫。
“尾遞回”和“基于累加器的遞回”并不相互排斥。尾遞回函式是任何呼叫自身作為至少一個代碼路徑上的最后一個動作的函式。基于累加器的遞回只是意味著將部分結果傳遞給遞回呼叫,作為將非尾遞回函式轉換為尾遞回函式的一種方式。
uj5u.com熱心網友回復:
好吧,首先,不確定基于累加器的遞回是什么意思?
其次,Scala只有while回圈,所有while回圈都可以用(尾)遞回表示;AFAIK。
第三,是的,我們更喜歡遞回while以避免可變性。
但是,遞回本身還是太低級了。通常,您應該更喜歡高階組合器,例如map或foldLeft
第四,雖然可變性包含在單個方法中是可以的,但通常最好是在任何地方保持一致并保持一切不可變(除非你有很好的理由否則),而不是僅僅因為隨機混合可變性和不變性。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/368220.html
