简体   繁体   中英

scala accessing a list object inside another list

I am trying to access a list object inside of another list with a specific type

val x = List ("item1" , "item2" , List ("a","b","c"))
val list_from_x :List [String]= x(2) // producing error 

I need my list_from_x of type to be of List [String] any idea how to I do such conversion ?

So x is of type List[Object] **, because you've used two different (otherwise unrelated) classes as elements of that list. You'll be unable to access elements other than of type Any without a type cast:

val listFromX = x(2).asInstanceOf[List[String]]

This is not type-safe, so you'll want to check element types ( x(2).isInstanceOf[List[_]] ) or pattern matching.


** Use the REPL to verify this; though val x: List[Any] = List ("item1" , "item2" , List ("a,b,c")) works

HList to the rescue:

import shapeless._
import Nat._

val x = "item1" :: "item2" :: List("a,b,c") :: HNil   
val list_from_x = x(_2)

list_from_x has the type List[String]

See the shapeless github page for more info.


As other answers have mentioned, a List can only hold elements of a certain type. For example, a List[String] can only hold String s. If you put elements of mixed types into a List , then the parametrised type of the List will become the most specific type common to all the elements.

The most specific type common to String and List is Any . So in this example, x is of type List[Any] :

val x = List("item1" , "item2" , List ("a,b,c"))

HList can hold elements of different types and maintain each element's type.

Scala compiler will simply say you got Objects (or may be Any) inside list x. That's why. You have to cast the 3rd element into a List in order to assign into a List variable.

The issue is List is defined as List[+A] ( source ). Which means List takes a type parameter of co-variant type. (You can think of co-variance as type converting from narrow to broader. For ex: if Dog extends Animal and if you do Animal a = new Dog() , you have a Dog (narrow) converting to Animal (broader))

x is of type List[Object] . Doing

scala> val x = List ("item1" , "item2" , List ("a,b,c"))
x: List[Object] = List(item1, item2, List(a,b,c))

val list_from_x :List [String]= x(2)

is ultimately converting from List[Object] (broader) to List[String] (narrow). Which is contra-variant. Hence the compiler threw error because List is meant to be co-variant.

For ex: the below is completely valid. Thanks to co-variance:

scala> val x = List("hello")
x: List[String] = List(sdf)

scala> val o:List[Object] = x
o: List[Object] = List(sdf)

More about it here and here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM