복붙노트

[SCALA] ClassTag 기초하여 패턴 매칭이 실패 프리미티브

SCALA

ClassTag 기초하여 패턴 매칭이 실패 프리미티브

나는 다음은 주어진 유형을 만족 컬렉션의 수집 요소에 가장 간결하고 정확한 형태가 될 것이라고 생각 :

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

    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

  2. from https://stackoverflow.com/questions/16825927/classtag-based-pattern-matching-fails-for-primitives by cc-by-sa and MIT license