2

If I try:

val someInput = List(('a', 2), ('b', 2))

for {
  (k,v) <- someInput
} yield (k,v)


 res0: List[(Char, Int)] = List((a,2), (b,2))

While if I did:

for {
  (k,v) <- someInput
} yield List(k,v)

res0: List[List[Int]] = List(List(97, 2), List(98, 2))

I don't understand why am I getting 97 & 98 when using a List?

alt-f4
  • 2,112
  • 17
  • 49

2 Answers2

4

The compiler automatically converts the key, which is a Char, to an Int (since JVM chars represent Unicode codepoints), because the value is an Int and Lists are homogenous. 97 and 98 are just the decimal representations of 'a' and 'b' in Unicode (and ASCII).

See this question for why Char is implicitly converted to Int (Note that Int is not converted to Char because it is 32 bits whereas Char is only 16, so it might be a lossy conversion).

You can also do

for {
  (k,v) <- someInput
} yield List((k,v))

so that you yield a singleton list of (Char, Int) and your types are preserved. The result would be List(List((a, 2)), List((b, 2)))

user
  • 7,435
  • 3
  • 14
  • 44
4

Scala 2 uses weak conformance relation when inferring the least upper bound of primitive number types such that

List('a', 2)

is typed to List[Int] instead of, perhaps expected, List[AnyVal]. The compiler inserts toInt

List('a'.toInt, 2)

as explained by SLS 6.26.1 Value Conversions

If has a primitive number type which weakly conforms to the expected type, it is widened to the expected type using one of the numeric conversion methods toShort, toChar, toInt, toLong, toFloat, toDouble defined in the standard library.

Weak conformance seems to be a dropped feature in Scala 3, for example,

Starting dotty REPL...
scala> val a = 'a'
     | val i = 2
val a: Char = a
val i: Int = 2

scala> List(a, i)
val res0: List[AnyVal] = List(a, 2)

where we see dotty deduced List[AnyVal]. If we try to force the type to List[Int] then warning is raised

scala> val l: List[Int] = List(a,i)
1 |val l: List[Int] = List(a,i)
  |                        ^
  |Use of implicit conversion method char2int in object Char should be enabled
  |by adding the import clause 'import scala.language.implicitConversions'
  |or by setting the compiler option -language:implicitConversions.
  |See the Scala docs for value scala.language.implicitConversions for a discussion
  |why the feature should be explicitly enabled.
val l: List[Int] = List(97, 2)
Mario Galic
  • 47,285
  • 6
  • 56
  • 98