Scala:无法将数组传递给需要 Seq 或 Iterable 的函数

Posted

技术标签:

【中文标题】Scala:无法将数组传递给需要 Seq 或 Iterable 的函数【英文标题】:Scala: Can't pass an Array to a function where Seq or Iterable is expected 【发布时间】:2021-09-05 17:53:31 【问题描述】:

我正在尝试编写一个通用函数,它接受一个类型参数 T,它是 Seq[String] 的子集,下面是示例示例

def test[T <:Seq[String]](c:T):T = 
c

我定义了一个变量,它是 Array[String]

val b = Array("test")

现在我希望这可以工作,但是,我收到如下错误

scala> test(b)
       ^
       error: inferred type arguments [Array[String]] do not conform to method test's type parameter bounds [T <: Seq[String]]
            ^
       error: type mismatch;
        found   : Array[String]
        required: T

我尝试将 T 定义为 Iterable[String] 的子集,但这也不起作用。

我知道 Scala 中的 Array 不是 Seq,但我希望它被隐式转换为 WrappedArray 和这个函数仍然有效。有人可以帮我看看这是怎么回事吗?

【问题讨论】:

这是因为 Array 来自 Java 领域并且位于标准 Scala 集合之外。它可以完成,但它不是微不足道的,并且在某种程度上取决于您正在运行的 Scala 版本。 【参考方案1】:

我知道 Scala 中的 Array 不是 Seq,但我希望它被隐式转换为 WrappedArray 并且这个函数仍然可以工作。有人可以帮我看看这是怎么回事吗?

这是怎么回事:

我希望它被隐式转换为 WrappedArray

你希望它不是真的。只有Scala Language Specification 里写的才是真的。

Section 3.2.6 Parameterized Types 表示“如果每个实际类型参数符合其界限,则参数化类型是格式良好的”。

而Section 3.5.2 Conformance 定义了“符合”的含义,并且没有在任何地方提及隐式转换。

因此,Array[String]Seq[String]一致,因此不是形式类型参数T 的有效实际类型参数。

【讨论】:

【参考方案2】:

要返回与收到的相同的集合类型,包括Array,您必须使用一些特殊的类型类。

这是一个(不是特别好)的例子。 (Scala 2.13.x)

import scala.collection.Factory
import scala.collection.generic.IsIterable

def test[CC[_]](c:CC[String]
               )(implicit isit: IsIterable[CC[String]] type A = String
                        , fac : Factory[String,CC[String]]
                ): CC[String] =
  isit(c).map(_.reverse).to(fac)

test(Array("abc"))           //res0: Array[String] = Array(cba)
test(Vector("Go","Jo"))      //res1: Vector[String] = Vector(oG, oJ)
test(List("my","dad","Bob")) //res2: List[String] = List(ym, dad, boB)

【讨论】:

以上是关于Scala:无法将数组传递给需要 Seq 或 Iterable 的函数的主要内容,如果未能解决你的问题,请参考以下文章

我有一个数组数组并将其传递给scala中的函数但出现错误

Scala如何将集合中的元素放入数组函数中

无法通过从两个不同子例程传递给新子例程的值来执行计算:Perl

如何将对象(或关联数组)作为属性值传递给我的 Web 组件

scala:将元组引用传递给函数

设置数组的长度属性