Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Scala promoting List[Any] to List[Long]?

In the following code:

def test(list: List[Any]): Unit = {
  list.foreach {
    v =>
    v match {
      case r: AnyRef => println(r + ": " + r.getClass.getName)
      case d: Double => println(d + ": Double")
      case f: Float=> println(f + ": Float")
      case b: Byte => println(b + ": Byte")
      case c: Char => println(c + ": Char")
      case s: Short => println(s + ": Short")
      case i: Int => println(i + ": Int")
      case l: Long=> println(l + ": Long")
      case b: Boolean => println(b + ": Boolean")
      case _ => throw new IllegalArgumentException("Unknown type: " + v)
    }
  }
}

test(List(0L, 1.asInstanceOf[Int], 2.asInstanceOf[Short]))

here is the output (Scala 2.8.1):

0: java.lang.Long
1: java.lang.Long
2: java.lang.Long

Why are the numbers being promoted to java.lang.Long? How can I do this so that they either keep their AnyVal types or get "boxed" to the equivalent AnyRef type?

like image 302
Ralph Avatar asked Dec 14 '10 19:12

Ralph


People also ask

What is difference between array and list in Scala?

Following are the point of difference between lists and array in Scala: Lists are immutable whereas arrays are mutable in Scala. Lists represents a linked list whereas arrays are flat.

Are Scala lists linked lists?

Specific to Scala, a list is a collection which contains immutable data, which means that once the list is created, then it can not be altered. In Scala, the list represents a linked list. In a Scala list, each element need not be of the same data type.

Is list homogeneous in Scala?

Lists are immutable --- the elements of a list cannot be changed, Lists are recursive (as you will see in the next subsection), Lists are homogeneous: A list is intended to be composed of elements that all have the same type.

How do you add elements to a list in Scala?

This is the first method we use to append Scala List using the operator “:+”. The syntax we use in this method is; first to declare the list name and then use the ':+' method rather than the new element that will be appended in the list. The syntax looks like “List name:+ new elements”.


3 Answers

I think the answer is in Section 3.5.3 of the language reference:

  • Byte weakly conforms to Short
  • Short weakly conforms to Int
  • Char weakly conforms to Int
  • Int weakly conforms to Long
  • Long weakly conforms to Float
  • Float weakly conforms to Double

Because of this, Scala infers that the common type between Short, Int and Long is Long and then converts the non-Long objects to Longs:

scala> List(0L, 0, 0: Short) 
res1: List[Long] = List(0, 0, 0)

If you want to use the whole chain of weak conformance, try:

scala> List(0: Byte, 1: Short, 'c', 3, 4L, 5.0f, 6.0)
res2: List[Double] = List(0.0, 1.0, 99.0, 3.0, 4.0, 5.0, 6.0)

And, of course to say that you want a List[Any], just add [Any] to your call to List:

scala> List[Any](0: Byte, 1: Short, 'c', 3, 4L, 5.0f, 6.0)
res11: List[Any] = List(0, 1, c, 3, 4, 5.0, 6.0)
like image 121
Steve Avatar answered Sep 28 '22 07:09

Steve


Type inference works by starting with the most restrictive type (e.g. Nothing) and widening until one type can contain everything. For numeric values, this means widening from Int to Long. But now, since the call is effectively to List[Long](ls: Long*) all the numeric values are promoted in advance.

So, for instance, all of these give the same list:

List(1, 2: Byte, 3: Long)
List(1L, 2, 3: Short)
List(1: Byte, 2: Long, 3: Byte)

namely a List[Long](1L, 2L, 3L). Now, if you don't like this behavior, specify the type of the list as AnyVal or Any:

List[Any](1, 2: Byte, 3: Long)
List.head.asInstanceOf[AnyRef].getClass   // java.lang.Integer

Edit: P.S. if you are specifying a constant of a certain type, you should just state the type (e.g. (2: Short)) instead of casting it to that type (e.g. 2.asInstanceOf[Short]).

like image 32
Rex Kerr Avatar answered Sep 28 '22 07:09

Rex Kerr


List[Any](0L, 1.asInstanceOf[Int], 2.asInstanceOf[Short])
like image 34
Alexey Romanov Avatar answered Sep 28 '22 06:09

Alexey Romanov