28

In javascript, we can do:

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

What is the Scala equivalent?

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
Leo
  • 2,860
  • 3
  • 24
  • 21

4 Answers4

41

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

Daniel Spiewak
  • 54,515
  • 14
  • 108
  • 120
  • 10
    This answer is awfully confusing -- the fact is that the OP's example works perfectly fine with a Scala `Array`, as @soc's answer shows. There are other options like `List` and `Vector`, but the reasons to use them or not use them have nothing to do with whether the use case is homogeneous or "pseudo-heterogeneous". – Greg Price Aug 31 '11 at 05:37
  • 1
    The answer is laced with jargon which may make it confusing. It also explains a lot if you get what he's saying. I suspect this phrasing was done on purpose, as the OP is coming from javascript. – providence Oct 01 '11 at 03:56
  • 4
    No, this is really how Scala natives speak. It's totally normal. (And I mean this honestly; I'm not at all trying to be sarcastic.) – James Moore May 07 '12 at 23:55
  • 2
    Isn't it also possible to pack all these things into a `Tuple`, as " a tuple combines a fixed number of items together so that they can be passed around as a whole. Unlike an array or list, a tuple can hold objects with different types." (taken from http://www.artima.com/pins1ed/collections.html) ? – herom Oct 22 '12 at 06:39
19

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].

soc
  • 27,983
  • 20
  • 111
  • 215
4

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

ePharaoh
  • 2,926
  • 2
  • 17
  • 11
  • 3
    Although notice that HList doesn't change the language at all, so if HList can do it, it's always been in Scala. – James Moore May 07 '12 at 23:56
2

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.

akauppi
  • 17,018
  • 15
  • 95
  • 120