如何在Scala中创建异构数组?

28

在JavaScript中,我们可以做到:

["a string", 10, {x : 1}, function() {}].push("another value");

Scala 的等效语言是什么?

4个回答

41

Scala中的数组非常同构。这是因为Scala是一种静态类型语言。如果你真的需要伪异构功能,你需要使用一个协变参数化的不可变数据结构(大多数不可变数据结构都是)。List是典型的例子,但Vector也是一个选择。然后你可以像这样做:

Vector("a string", 10, Map("x" -> 1), ()=>()) + "another value"

结果的类型将为Vector[Any]。 在静态类型方面并不是很有用,但是所有承诺的内容都将被包含在其中。

顺便说一句,在Scala中数组的“字面量语法”如下:

Array(1, 2, 3, 4)     // => Array[Int] containing [1, 2, 3, 4]

参见: 有关持久向量的更多信息


10
这个答案非常令人困惑--事实上,正如@soc的回答所示,Scala的Array可以完美地处理OP的例子。还有其他选项,比如ListVector,但是使用它们或不使用它们的原因与使用情况是同构还是“伪异构”无关。 - Greg Price
1
答案充斥着术语,这可能会让人感到困惑。但如果你理解了他的意思,它也解释得很清楚。我怀疑这种措辞是有意为之的,因为提问者来自JavaScript领域。 - providence
4
不,这就是Scala本地人说话的方式,非常正常。(我是认真的,我完全没有试图讽刺。) - James Moore
2
难道不也可以将所有这些东西打包成一个“元组”吗?因为“元组将固定数量的项组合在一起,以便它们可以作为整体传递。与数组或列表不同,元组可以容纳具有不同类型的对象。”(摘自http://www.artima.com/pins1ed/collections.html) - herom

19

在Scala中,会选择能够容纳所有值的最特定数组元素类型,此时需要最通用的类型Any,它是所有其他类型的超类型:

Array("a string", 10, new { val x = 1 }, () => ()) :+ "another value"

得到的数组类型将为 Array[Any]


4

3
需要翻译的内容:Although notice that HList doesn't change the language at all, so if HList can do it, it's always been in Scala.尽管注意到HList并没有改变语言,因此如果HList能够实现某个功能,它一直存在于Scala中。 - James Moore

2

个人而言,我可能会像herom在评论中提到的那样使用元组。

scala> ("a string", 10, (1), () => {})
res1: (java.lang.String, Int, Int, () => Unit) = (a string,10,1,<function0>)

但是你不能轻易地向这样的结构追加内容。

ePharaoh提到的HList“为此而生”,但我个人可能会避开它。它在类型编程方面很重,因此可能会带来一些意外负担(例如在编译时创建了许多类)。只要小心谨慎。上述代码的HList(需要MetaScala库)可能是(未经证明,因为我不使用MetaScala):

scala> "a string" :: 10 :: (1) :: () => {} :: HNil

你可以附加等等(至少是前置)到这样的列表中,它会知道类型。前置创建一个新类型,其旧类型为尾部。
然后还有一种方法没有提到。类(特别是case类)在Scala上非常轻便,你可以将它们制作成单行代码:
scala> case class MyThing( str: String, int: Int, x: Int, f: () => Unit )
defined class MyThing

scala> MyThing( "a string", 10, 1, ()=>{} )
res2: MyThing = MyThing(a string,10,1,<function0>)

当然,这也不会处理追加操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接