给出一个假设的可变链表(让我们假设这是一个给定的结构 - 所以没有关于改变它的建议,请):
trait CList[T]
trait CNil [T] extends CList[T]
trait CCons[T] extends CList[T] {
def head: T
def tail: CList[T]
}
考虑到Scala的类型擦除,如何在不进行转换的情况下迭代它:
@annotation.tailrec def lastValue[T](l: CList[T]): Option[T] = l match {
case _: CNil [_] => None
case c: CCons[_] => lastValue(c.asInstanceOf[CCons[T]]) // ouch!
}
CList
在T
中是不变的,所以应该有办法实现这个目标吗?
答案 0 :(得分:4)
您可以尝试定义提取器:
object CNil {
def unapply[T](clist: CList[T]): Boolean = clist.isInstanceOf[CNil[_]]
}
object CCons {
def unapply[T](clist: CList[T]): Option[(T, CList[T])] = clist match {
case _: CNil[_] => None
case c: CCons[_] => Some(c.head, c.tail)
}
}
@annotation.tailrec def lastValue[T](l: CList[T]): Option[T] = l match {
case CNil() => None
case CCons(head, tail) => lastValue(tail)
}
如果您不能将它们放在与定义原始特征的文件相同的文件中,您可能必须给它们另一个名称。
另一方面,你的lastValue
函数的实现可能不符合你的预期......相反,这个怎么样呢?
def lastValue[T](clist: CList[T]): Option[T] = {
@annotation.tailrec
def lastValue0(prevValue: Option[T], clist: CList[T]): Option[T] =
clist match {
case CNil() => prevValue
case CCons(head, tail) => lastValue0(Some(head), tail)
}
lastValue0(None, clist)
}