How do I create a heterogeneous Array in Scala?

前端 未结 4 544
情书的邮戳
情书的邮戳 2020-12-30 21:31

In javascript, we can do:

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

What is the Scala equivalent?

相关标签:
4条回答
  • 2020-12-30 21:45

    Scala might get the ability for a "heterogeneous" list soon: HList in Scala

    0 讨论(0)
  • 2020-12-30 21:55

    Scala will choose the most specific Array element type which can hold all values, in this case it needs the most general type Any which is a supertype of every other type:

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

    The resulting array will be of type Array[Any].

    0 讨论(0)
  • 2020-12-30 21:58

    Arrays in Scala are very much homogeneous. This is because Scala is a statically typed language. If you really need pseudo-heterogeneous features, you need to use an immutable data structure that is parametrized covariantly (most immutable data structures are). List is the canonical example there, but Vector is also an option. Then you can do something like this:

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

    The result will be of type Vector[Any]. Not very useful in terms of static typing, but everything will be in there as promised.

    Incidentally, the "literal syntax" for arrays in Scala is as follows:

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

    See also: More info on persistent vectors

    0 讨论(0)
  • 2020-12-30 22:00

    Personally, I would probably use tuples, as herom mentions in a comment.

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

    But you cannot append to such structures easily.

    The HList mentioned by ePharaoh is "made for this" but I would probably stay clear of it myself. It's heavy on type programming and therefore may carry surprising loads with it (i.e. creating a lot of classes when compiled). Just be careful. A HList of the above (needs MetaScala library) would be (not proven since I don't use MetaScala):

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

    You can append etc. (well, at least prepend) to such a list, and it will know the types. Prepending creates a new type that has the old type as the tail.

    Then there's one approach not mentioned yet. Classes (especially case classes) are very light on Scala and you can make them as one-liners:

    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>)
    

    Of course, this will not handle appending either.

    0 讨论(0)
提交回复
热议问题