首页 > 解决方案 > 无法重写递归调用:它不在尾部位置

问题描述

我一直在玩 Dotty 并尝试实现一个简单的 List。这就是我实现它的方式:

enum List[+A] {
  case Cons(head :A, tail: List[A])
  case Nil extends List[Nothing]
}

我遇到的问题是这个实现无法编译Cannot rewrite recursive call: it is not in tail position

@tailrec
def drop[A](n: Int, as: List[A]): List[A] = 
  (n,as) match
    case (0, _) => as
    case (_, Nil) => Nil
    case (x, Cons(_, tail)) => drop(x-1, tail)

在另一个文件上,我尝试了相同的实现,使用标准库的列表,它编译:

@tailrec
def drop[A](n: Int, as: List[A]): List[A] = 
  (n,as) match
    case (0, _) => as
    case (_, Nil) => Nil
    case (x, _ :: tail) => drop(x-1, tail)

也许我只是累了,没有看到明显的错误,但也许这里还有别的东西?extends List[Nothing]我必须添加以使代码编译引起的任何奇怪之处?

谢谢!

编辑

标签: scaladottyscala-3

解决方案


在 Dotty 0.25.0-bin-20200429-c5a76f0-NIGHTLY

import scala.annotation.tailrec

enum List[+A] {
  case Cons(head :A, tail: List[A])
  case Nil extends List[Nothing]

  @tailrec
  def drop[A](n: Int, as: List[A]): List[A] =
    (n,as) match
      case (0, _) => as
      case (_, Nil) => Nil
      case (x, Cons(_, tail)) => drop(x-1, tail)
}

生产

TailRec optimisation not applicable, method drop is neither private nor final so can be overridden

如果您将drop其设为 final 或 private,则代码会编译。


推荐阅读