0

我正在研究应该是一段微不足道的代码。我想获取一个列表,并将其转换为等效的数组:

import scala.collection.JavaConverters

object Help extends App {
  def f1[T](lst: List[T]) = {
    lst.toArray
  }

  val x = List(1, 2, 3)
  println(f1(x))
}

运行此代码给出:

"No ClassTag available for T"

我怎样才能避免这个问题;我来自 Python 背景,因此希望能有一个回复让我了解这里的机制。

谢谢!

4

1 回答 1

4

尝试像这样添加隐式ClassTag参数

import scala.reflect.ClassTag

def f1[T](lst: List[T])(implicit ev: ClassTag[T]) = {
  lst.toArray
}

如果我们看一下签名,原因就很清楚了toArray

def toArray[B >: A: ClassTag]: Array[B]

这相当于

def toArray[B >: A](implicit ev: ClassTag[B]): Array[B]

所以你必须将隐式参数从f1down 线程化到toArray.

将不胜感激让我了解这里的机制的回应

关键是要理解Array不是真正的Scala 集合。这一次,它不是Iterable

implicitly[Array[Int] <:< Iterable[Int]] // error

与真正的 Scala 集合之间的另一个区别Array是不需要ClassTag真正的 Scala 集合。原因是 Scala 集合经历了类型擦除过程,这意味着运行时知道它是 aList但不区分List[Int]and List[String],例如。然而,这并不成立ArrayArray[Int]在运行时和之间确实存在差异Array[String]。因此ClassTag,发明了一种用于携带类型信息的机制,该信息仅存在于编译时,一直到运行时,因此Array可以具有 Java 中的行为。

您将遇到其他差异,例如

Array(42) == Array(42)  // false
List(42) == List(42)    // true

最佳做法是尽可能避免Array

于 2020-06-09T23:36:55.507 回答