Scala:为什么这个函数不是尾递归?

时间:2016-12-27 18:31:04

标签: scala recursion functional-programming tail-recursion purely-functional

我有Merge Sort的实现:

import scala.annotation.tailrec

object MergeSort {
  def sortBy[T]: ((T, T) => Int) => Seq[T] => Seq[T] = comparator => seqToSort => {
    @tailrec
    def merge(xs : Seq[T], ys : Seq[T], accum : Seq[T] = Seq()) : Seq[T] = (xs, ys) match {
      case (Seq(), _) => ys ++ accum
      case (_, Seq()) => xs ++ accum
      case (x::rx, y::ry) =>
        if(comparator(x, y) < 0)
          merge(xs, ry, y +: accum)
        else
          merge(rx, ys, x +: accum)
    }

    @tailrec
    // Problem with this function
    def step : Seq[Seq[T]] => Seq[T] = {
      case Seq(xs) => xs
      case xss =>
        val afterStep = xss.grouped(2).map({
          case Seq(xs) => xs
          case Seq(xs, ys) => merge(xs, ys)
        }).toSeq
        // Error here
        step(afterStep)
    }

    step(seqToSort.map(Seq(_)))
  }
}

它无法编译。它表示 step 函数中的递归调用不在尾部位置。 但它处于尾部位置。有没有办法在没有蹦床的情况下解决它?

1 个答案:

答案 0 :(得分:6)

原因是step是一个返回签名函数的函数:Seq[Seq[T]] => Seq[T]。因此递归调用不会直接调用相同的方法,而是首先获取此函数,然后为给定的参数调用它,这不是尾递归。

要解决此错误,您必须以这种方式声明step

@tailrec
def step(seq: Seq[Seq[T]]): Seq[T] = seq match {
  ...
}