Scala generic set

In Scala 2.9.1

FROM

def collectFirstOfT[T](la: List[_])(implicit m:Manifest[T]) : Option[T] = { la.collect{case x if m.erasure.isAssignableFrom(x.getClass) => x}. headOption.asInstanceOf[Option[T]]} class A class B 

why is this expression:

 val oB:Option[B] = collectFirstOf(List(new A,new B)) 

compiles but collects some (A) but

 val oB =collectFirstOf[B](List(new A,new B)) 

works great.

How to deduce T from option [T]?

+6
source share
3 answers

You should look at the following line as two separate parts, left side = and right:

 val oB: Option[B] = collectFirstOf(List(new A,new B)) 

What you expect from here is that the type of the expression collectFirstOf (rvalue) should be inferred from the value type of oB. The compiler cannot do this. You have to say specifically what type you expect. Take the following example:

 val v: Long = 1 + 4 

The expression type 1 + 4 is Int. Then this int is converted to Long. The compiler does not and cannot conclude that you want 1 or 4 to be long:

So, to fix your problem, you need to tell the compiler what type you expect, otherwise it assumes java.lang.Object:

 val oB = collectFirstOf[B](List(new A,new B)) 

So, the manifest is correctly assigned, and everything is fine with the world. So why does the following compile:

 val oB:Option[B] = collectFirstOfT(List(new A,new B)) oB: Option[B] = Some( A@10f3a9c ) 

at first glance, it seems that this should not work, but it is. This is because collectFirstOfT actually returns the [Nothing] parameter, which can be safely converted to the [B] option:

 scala> val f = collectFirstOfT(List(new A,new B)) f: Option[Nothing] = Some( A@baecb8 ) scala> f.asInstanceOf[Option[B]] res4: Option[B] = Some( A@baecb8 ) 
+3
source

It:

 val oB:Option[B] = collectFirstOfT(List(new A,new B)) 

This is equivalent to this:

val oB: Option [B] = collectFirstOfT [Nothing] (List (new A, new B))

Since Nothing is a subclass of everything, it can be assigned to A Alas, it can also be assigned from B , which means that you can assign Option[Nothing] to Option[B] .

Fun fact: this is true because Option is a co-option. If this were not so, then T should be output as B , which would make it work.

Fun fact 2: this code does not compile on yesterday's trunk.

+3
source

Because the compiler cannot deduce T from agruments, so you must write it explicitly. In the first case, collect accepts the entire list.

0
source

Source: https://habr.com/ru/post/913016/


All Articles