[SCALA] ClassTag 기초하여 패턴 매칭이 실패 프리미티브
SCALAClassTag 기초하여 패턴 매칭이 실패 프리미티브
나는 다음은 주어진 유형을 만족 컬렉션의 수집 요소에 가장 간결하고 정확한 형태가 될 것이라고 생각 :
def typeOnly[A](seq: Seq[Any])(implicit tag: reflect.ClassTag[A]): Seq[A] =
seq.collect {
case tag(t) => t
}
그러나 이것은 단지 AnyRef 유형,하지 프리미티브 작동 :
typeOnly[String](List(1, 2.3, "foo")) // ok. List(foo)
typeOnly[Double](List(1, 2.3, "foo")) // fail. List()
물론 직접적인 형태로 작동합니다 :
List(1, 2.3, "foo") collect { case d: Double => d } // ok. List(2.3)
그래서 위의 방법을 해결하기 (간단한!) 방법이 있어야합니다.
해결법
-
==============================
1.그것은 예에서 박스거야, 그렇지?
그것은 예에서 박스거야, 그렇지?
scala> typeOnly[java.lang.Double](vs) res1: Seq[Double] = List(2.3)
업데이트 : "권투는 눈에 보이지 않는 있어야하는데, 플러스 또는 마이너스"오라클이 적합 비밀이었다. 이 경우는 플러스 또는 마이너스 인 경우 모르겠어요.
내 감각은, 그렇지 않으면 모든 빈 허구이기 때문에 그것은 버그라는 것이다.
더 델포이 demurring : ". 나는 주어진 예제가 할 것으로 예상된다 모르겠어요" 지정되지 않은 것을 알 수는, 누구에 의해 예상했다.
이 boxedness에 대해 알고 자 질문에 유용한 운동, 그리고 상자는 무엇인가? 이 컴파일러는 모든 사람들이 이미보고 선이 있어야한다 알고에도 불구하고, 공중에 매달린 재생 카드를 유지하는 와이어를 은폐하기 위해 열심히 작업 마술사 인 것처럼입니다.
scala> def f[A](s: Seq[Any])(implicit t: ClassTag[A]) = s collect { | case v if t.runtimeClass.isPrimitive && | ScalaRunTime.isAnyVal(v) && | v.getClass.getField("TYPE").get(null) == t.runtimeClass => | v.asInstanceOf[A] | case t(x) => x | } f: [A](s: Seq[Any])(implicit t: scala.reflect.ClassTag[A])Seq[A] scala> f[Double](List(1,'a',(),"hi",2.3,4,3.14,(),'b')) res45: Seq[Double] = List(2.3, 3.14)
ScalaRunTime는 API를 지원하지 않습니다 - isAnyVal에 대한 호출이 유형에 단지 일치; 하나는 바로 "TYPE"필드가 존재하는지 확인할 수 있습니다 또는
Try(v.getClass.getField("TYPE").get(null)).map(_ == t.runtimeClass).getOrElse(false)
그러나 좋은 한 줄에 다시 얻을, 당신은 특별히 맡았다 추출을 처리하기 위해 자신의 ClassTag을 롤백 할 수 있습니다.
2.11 버전. 이 가장자리 출혈이되지 않을 수도 있습니다,하지만 그것은 최근 소작 가장자리입니다.
object Test extends App { implicit class Printable(val s: Any) extends AnyVal { def print = Console println s.toString } import scala.reflect.{ ClassTag, classTag } import scala.runtime.ScalaRunTime case class Foo(s: String) val vs = List(1,'a',(),"hi",2.3,4,Foo("big"),3.14,Foo("small"),(),null,'b',null) class MyTag[A](val t: ClassTag[A]) extends ClassTag[A] { override def runtimeClass = t.runtimeClass /* override def unapply(x: Any): Option[A] = ( if (t.runtimeClass.isPrimitive && (ScalaRunTime isAnyVal x) && x.getClass.getField("TYPE").get(null) == t.runtimeClass) Some(x.asInstanceOf[A]) else super.unapply(x) ) */ override def unapply(x: Any): Option[A] = ( if (t.runtimeClass.isPrimitive) { val ok = x match { case _: java.lang.Integer => runtimeClass == java.lang.Integer.TYPE //case _: java.lang.Double => runtimeClass == java.lang.Double.TYPE case _: java.lang.Double => t == ClassTag.Double // equivalent case _: java.lang.Long => runtimeClass == java.lang.Long.TYPE case _: java.lang.Character => runtimeClass == java.lang.Character.TYPE case _: java.lang.Float => runtimeClass == java.lang.Float.TYPE case _: java.lang.Byte => runtimeClass == java.lang.Byte.TYPE case _: java.lang.Short => runtimeClass == java.lang.Short.TYPE case _: java.lang.Boolean => runtimeClass == java.lang.Boolean.TYPE case _: Unit => runtimeClass == java.lang.Void.TYPE case _ => false // super.unapply(x).isDefined } if (ok) Some(x.asInstanceOf[A]) else None } else if (x == null) { // let them collect nulls, for example if (t == ClassTag.Null) Some(null.asInstanceOf[A]) else None } else super.unapply(x) ) } implicit def mytag[A](implicit t: ClassTag[A]): MyTag[A] = new MyTag(t) // the one-liner def g[A](s: Seq[Any])(implicit t: ClassTag[A]) = s collect { case t(x) => x } // this version loses the "null extraction", if that's a legitimate concept //def g[A](s: Seq[Any])(implicit t: ClassTag[A]) = s collect { case x: A => x } g[Double](vs).print g[Int](vs).print g[Unit](vs).print g[String](vs).print g[Foo](vs).print g[Null](vs).print }
2.10.x, 암시 적 해상도이기 때문에 보일러의 추가 라인 - 글쎄, 우리는 그냥 작동하지 않습니다 말할 것이다,이 생겼 말을하지 않습니다.
// simplified version for 2.10.x object Test extends App { implicit class Printable(val s: Any) extends AnyVal { def print = Console println s.toString } case class Foo(s: String) val vs = List(1,'a',(),"hi",2.3,4,Foo("big"),3.14,Foo("small"),(),null,'b',null) import scala.reflect.{ ClassTag, classTag } import scala.runtime.ScalaRunTime // is a ClassTag for implicit use in case x: A class MyTag[A](val t: ClassTag[A]) extends ClassTag[A] { override def runtimeClass = t.runtimeClass override def unapply(x: Any): Option[A] = ( if (t.runtimeClass.isPrimitive && (ScalaRunTime isAnyVal x) && (x.getClass getField "TYPE" get null) == t.runtimeClass) Some(x.asInstanceOf[A]) else t unapply x ) } // point of the exercise in implicits is the type pattern. // there is no need to neutralize the incoming implicit by shadowing. def g[A](s: Seq[Any])(implicit t: ClassTag[A]) = { implicit val u = new MyTag(t) // preferred as more specific s collect { case x: A => x } } s"Doubles? ${g[Double](vs)}".print s"Ints? ${g[Int](vs)}".print s"Units? ${g[Unit](vs)}".print s"Strings? ${g[String](vs)}".print s"Foos? ${g[Foo](vs)}".print }
댓글을 추진 :
@WilfredSpringer 누군가가 당신을 들었다. SI-6967
from https://stackoverflow.com/questions/16825927/classtag-based-pattern-matching-fails-for-primitives by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 스칼라는 : 어떻게 어떤 경우 클래스의 추상 복사 가능한 슈퍼 클래스를 정의? (0) | 2019.11.23 |
---|---|
[SCALA] 어떻게 스칼라에서 일반적인 방법으로 형질의 인스턴스를 만들려면 어떻게해야합니까? (0) | 2019.11.23 |
[SCALA] 어떻게 스칼라 방법 정적을해야합니까? (0) | 2019.11.23 |
[SCALA] 어레이 스파크 SQL의 요소 범위를 선택 (0) | 2019.11.23 |
[SCALA] 어떻게 여러 개의 입력과 implicits는 스칼라에서 사용할 수 있습니까? (0) | 2019.11.23 |