简体   繁体   English

Scala @tailrec折叠

[英]Scala @tailrec with fold

Does the scala's @tailrec annotation supports Option.fold method? Scala的@tailrec注释是否支持Option.fold方法?

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

This code results in error: 此代码导致错误:

Could not optimize @tailrec annotated method test: it contains a recursive call not in tail position 无法优化@tailrec带注释的方法测试:它包含不在尾部位置的递归调用

This problem can be solved with pattern matching but I find fold looks much cleaner. 这个问题可以通过模式匹配解决,但是我发现fold看起来更干净。

When you want to write a tail recursive function in Scala, your call to the tail recursive function needs to be in the last position (hence tail call recursion). 当您要在Scala中编写尾部递归函数时,对尾部递归函数的调用必须位于最后一个位置(因此, 尾部调用递归)。

In your case Option.fold is last and the Scala compiler cannot figure out that the result of fold is always a call to test . 就您而言, Option.fold是最后一个,Scala编译器无法弄清楚fold的结果始终是对test的调用。

You can use TailCals , to write a tail recursive function using fold : 您可以使用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

It is for you to deside if you find using TailRec more concise than using pattern matching : 如果您发现使用TailRec比使用模式匹配更简洁,这是您需要考虑的问题:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM