4

たとえば、特定の型 (例: )Iterable[A]のすべての要素を絞り込みたい場合は、次のようにします。String

as filter { _.isInstanceOf[String] }

ただし、これを を介して実行できるとして使用することが明らかに望ましいです。Iterable[String]map

as filter { _.isInstanceOf[String] } map { _.asInstanceOf[String] }

これはかなり醜いです。もちろん、flatMap代わりに使用できます:

as flatMap[String] { a => 
  if (a.isInstanceOf[String]) 
    Some(a.asInstanceOf[String]) 
  else
    None
}

しかし、これがもっと読みやすいかどうかはわかりません! 変換narrowを介して使用できる関数を作成しました。implicit

as.narrow(classOf[String])

しかし、私が見落としていたより良い組み込みメカニズムがあるかどうか疑問に思っていました. List[A]特に、私の関数のように aを aList[String]ではなく、 aに狭められるとよいでしょうIterable[String]

4

4 に答える 4

8

isInstanceOf/のScalaシンタックスシュガーasInstanceOfはパターンマッチングです:

as flatMap { case x: String => Some(x); case _ => None }

これはを使用するため、flatMap通常、最初に必要だったのと同じコレクションを返す必要があります。

Scala 2.8には、その種のパターンを実行する実験的な関数があり、オブジェクトPartialFunction内で定義されています。したがって、Scala2.8では次のことができます。

as flatMap (PartialFunction.condOpt(_ : Any) { case x: String => x })

これは主に、最初にその関数をインポートしなかったために大きく見えます。しかし、繰り返しになりますが、Scala 2.8には、より直接的な方法があります。

as collect { case x: String => x }
于 2009-09-28T18:16:14.210 に答える
3

ちなみに、これはの完全な実装ですnarrow。質問で与えられた署名とは異なり、それはManifestいくつかの文字を避けるために暗黙を使用します:

implicit def itrToNarrowSyntax[A](itr: Iterable[A]) = new {
  def narrow[B](implicit m: Manifest[B]) = {
    itr flatMap { x => 
      if (Manifest.singleType(x) <:< m)
        Some(x)
      else
        None
    }
  }
}

val res = List("daniel", true, 42, "spiewak").narrow[String]  
res == Iterable("daniel", "spiewak")

残念ながら、特定のタイプ(例List[String])に絞り込むIterable[String]のは少し難しいです。これは、Scala 2.8.0の新しいコレクションAPIを使用して、より高い種類を活用することで実行できますが、現在のフレームワークでは実行できません。

于 2009-09-28T19:38:42.287 に答える
1

形状保持: 今は少し急いでいるので、キャストをそのままにしておきますが、削除できると確信しています. これはトランクで機能します:

import reflect.Manifest
import collection.Traversable
import collection.generic.CanBuildFrom
import collection.mutable.ListBuffer

object narrow {
  class Narrower[T, CC[X] <: Traversable[X]](coll: CC[T])(implicit m1: Manifest[CC[T]], bf: CanBuildFrom[CC[T], T, CC[T]]) {
    def narrow[B: Manifest]: CC[B] = {
      val builder = bf(coll)      
      def isB(x: T): Option[T] = if (Manifest.singleType(x) <:< manifest[B]) Some(x) else None

      coll flatMap isB foreach (builder += _)
      builder mapResult (_.asInstanceOf[CC[B]]) result
    }
  }

  implicit def toNarrow[T, CC[X] <: Traversable[X]](coll: CC[T])(implicit m1: Manifest[CC[T]], bf: CanBuildFrom[CC[T], T, CC[T]]) = 
    new Narrower[T,CC](coll)

  def main(args: Array[String]): Unit = {
    println(Set("abc", 5, 5.5f, "def").narrow[String])
    println(List("abc", 5, 5.5f, "def").narrow[String]) 
  }
}

それを実行する:

Set(abc, def)
List(abc, def)
于 2009-10-29T16:14:29.837 に答える
1

将来使用する可能性があります:

for(a :Type <- itr) yield a

しかし、今はうまくいきません。詳細については、次のリンクにアクセスして ください。 http://lampsvn.epfl.ch/trac/scala/ticket/1089 http://lampsvn.epfl.ch/trac/scala/ticket/900

于 2009-09-30T04:02:26.957 に答える