CruncherBigData
CruncherBigData

Reputation: 1122

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 ?

Upvotes: 0

Views: 1468

Answers (4)

theon
theon

Reputation: 14380

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

Upvotes: 2

Jatin
Jatin

Reputation: 31724

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

Upvotes: 0

lasantha
lasantha

Reputation: 855

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.

Upvotes: 0

Richard Sitze
Richard Sitze

Reputation: 8463

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

Upvotes: 2

Related Questions