首页 > 解决方案 > 何时对递归函数/方法使用辅助递归函数/方法

问题描述

在函数式编程课程的工作表中,我被要求用 Scala 编写一个函数(尽管我认为教授可能指的是方法),该函数递归地在新行的列表中打印元素,并带有行号,结果如下:

    scala> printCounter (List ("the", "rain", "in", "spain"))
[001] the
[002] rain
[003] in
[004] spain

工作表上提供的解决方案如下所示:

def printCounterAux [X] (xs:List[X], count:Int) : Unit = {
  xs match {
    case Nil   => ()
    case y::ys => {
      println ("[%03d] %s".format (count, y))
      printCounterAux (ys, count + 1)
    }
  }
}

def printCounter [X] (xs:List[X]) : Unit = {
  printCounterAux (xs, 1)
}

printCounter (List ("the", "rain", "in", "spain"))

我没有想到要创建一个辅助方法。作为仍在处理递归的人,我的问题是:您如何知道何时需要创建辅助递归方法?在这种情况下,信号会是多个参数吗?还是仅仅是大量接触这些方法的问题?非常感谢您可以分享的任何建议。干杯。

标签: scalarecursion

解决方案


printCounterAux具有不同于printCounter. 不仅如此,API 的变化与方法的功能无关,纯粹是一个实现细节。(例如,已经printCounter用循环实现了,就没有必要了。)

因此,您希望对消费者隐藏此 API。

然而,为了真正正确地隐藏此 API,printCounterAux应该是 的内部函数printCounter如下所示:

def printCounter[X](xs: List[X]): Unit = {
  printCounterAux()

  def printCounterAux[X](xs: List[X] = xs, count: Int = 1): Unit = xs match {
    case Nil     => ()
    case y :: ys => {
      println("[%03d] %s".format(count, y))
      printCounterAux(ys, count + 1)
    }
  }
}

printCounter(List("the", "rain", "in", "spain"))

请注意,在许多情况下,您需要随身携带某种“状态”,而在纯函数式语言的递归函数中,携带该状态的一个非常方便的地方是函数的参数。因此,您通常必须修改参数列表以添加状态参数(如count本例所示),该参数不应暴露给消费者。


推荐阅读