6

Scala2.9.1では

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

なぜこの表現:

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

コンパイルしますが、Some(A)を収集しますが、

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

正常に動作します。

Option [T]からTを推測する方法は?

4

3 に答える 3

3

これ:

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

これと同等です:

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

Nothingはすべてのサブクラスであるため、から割り当て可能ですA。残念ながら、から割り当てるBこともできます。つまり、にを割り当てることができます。Option[Nothing]Option[B]

おもしろい事実:Option共変であるため、それは真実です。そうでない場合は、Tとして推論する必要がありBます。これにより、機能するようになります。

おもしろい事実2:このコードは昨日のトランクではコンパイルされません。

于 2012-04-12T14:09:17.440 に答える
3

次の行を、=の左側と右側の2つの別個の部分として見る必要があります。

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

ここで期待しているのは、collectFirstOf式の型(右辺値)は、値oBの型から推測される必要があるということです。コンパイラはこれを行うことができません。あなたはあなたが期待しているタイプを具体的に言わなければなりません。次の例を見てください。

val v: Long = 1 + 4

式1+4のタイプはIntです。次に、このintはLongに変換されます。コンパイラーは、1または4を長くしたいことを推測できません。

したがって、問題を修正するには、予期しているタイプをコンパイラーに通知する必要があります。そうでない場合は、java.lang.Objectを想定します。

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

したがって、マニフェストは正しく割り当てられ、すべてが世界に順調に進んでいます。では、なぜ以下もコンパイルされるのでしょうか。

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

一見すると、これは機能するはずではないように見えますが、機能します。これは、collectFirstOfTが実際にOption [Nothing]を返すためです。これは、Option[B]に安全に変換できます。

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)
于 2012-04-12T12:44:29.503 に答える
0

コンパイラはTagrumentsから推測できないため、明示的に記述する必要があります。最初のケースでcollectは、すべてのリストを受け入れます。

于 2012-04-12T10:15:37.770 に答える