避免在尾递归调用中传递累积参数

时间:2017-10-17 11:00:10

标签: scala

说我想简单地将字符串转换为int:

  

列表(“1”,“3”,“55”,“x”,“7”)=>清单(1,3,55,7)

执行此操作的一种方法是以下递归调用:

def recurse1(strs: List[String]): List[Int] = strs match {
    case h :: t =>
        try {
            h.toInt :: recurse1(t)
        }
        catch {
            case _ : java.lang.NumberFormatException =>
                recurse1(t)
        }
    case _ =>
        List()
}

但是由于代码中的第4行,这不能编译为尾递归。因此,为了解决这个问题,我可以按照以下方式重新定义函数:

def recurse2(strs: List[String], accum: List[Int] = List()): List[Int] = strs match {
    case h :: t =>
        try {
            recurse2(t, h.toInt :: accum)
        }
        catch {
            case _ : java.lang.NumberFormatException =>
                recurse2(t, accum)
        }
    case _ =>
        accum.reverse
}

所以我的问题是这个。是否有一个我可以在scala中使用的成语,它允许我递归地执行此尾部但不必传递变量来累积值?

2 个答案:

答案 0 :(得分:1)

也许您的recurse方法仅用于说明,但为了完整起见,我将向@ pamu添加如何使用标准函数的答案:

  def foo(ss: List[String]): List[Int] = 
    ss.map(s => Try(s.toInt).toOption)
      .filter(_.isDefined)
      .map(_.get)

  def foo(ss: List[String]): List[Int] =
    ss.map(s => Try(s.toInt))
      .collect { case Success(n) => n }

答案 1 :(得分:0)

通常,我看到程序员编写一个辅助函数,它接受许多参数(内部),这些参数特定于您正在使用的方法/算法。他们围绕丑陋的内部函数编写了一个最小的接口函数,它是尾递归的,只需要输入并隐藏内部机制。

def reverse(input: List[Sting]): List[Int] = {
 def helper(strs: List[String], accum: List[Int] = List()): List[Int] = 
  strs match {
      case h :: t =>
          try {
             helper(t, h.toInt :: accum)
          }
          catch {
              case _ : java.lang.NumberFormatException =>
                 helper(t, accum)
          }
      case _ =>
          accum.reverse
  }
  helper(input, List.empty[Sting])
}