복붙노트

[SCALA] 어떻게 스칼라의 (2.8) 매니페스트 작동합니까?

SCALA

어떻게 스칼라의 (2.8) 매니페스트 작동합니까?

나는 제네릭 상당히 많이 사용하게 일부 스칼라 코드가, 나는 예를 들어 나는 일반적인 유형의 새 개체를 인스턴스화 할 (매개 변수화 제약에서 매니페스트를 사용하여 나를 유형의 삭제 문제를 해결할 수 있도록 할 수있는 문서에서 수집 한 ). 만, 나는 어떻게이 작품에 대한 자세한 내용을 이해하고 싶습니다. 그것은 거의 모든 호출 사이트에 대한 항목을 점점 해시 맵의 일종 같은 느낌 ... 여기 캔 사람이 정교한?

class Image[T <: Pixel[T] : Manifest](fun() => T, size: Array[Int], data: Array[T]) {
    def this(fun: () => T, size: Array[T]) {
        this(fun, size, new Array[T](size(0) * size(1));
    }
}

이것은 내가 사이트에서 발견 한 문서의에 포함하지 않는 것 무엇인가, 그리고 구글 I 대부분 매우 다른 구문이 이전 게시물을 얻을에, 2.8 많은 것들을 변경 갖고있는 것 같아요 때문에, I 'm는 확실하지 사람들은 여전히 ​​정확합니다.

해결법

  1. ==============================

    1.나도 같은 질문에 대답 할 수있는 퀘스트 스칼라의 소스 코드를 통해 발굴 이후 오랜만이야 ...하지만 짧은 대답은 내가 기억으로 -

    나도 같은 질문에 대답 할 수있는 퀘스트 스칼라의 소스 코드를 통해 발굴 이후 오랜만이야 ...하지만 짧은 대답은 내가 기억으로 -

    매니페스트 (가 런타임에 사용하지 않는) 컴파일러가 타입 삭제 주위에 얻을 수있는 치트 코드입니다. 그것은 여러 코드 경로가 일치 매니페스트 가능한 입력 형식 컴파일 시간에 발생되도록한다.

    매니페스트는 암시 적으로 해결하지만, 매니페스트 유형이 무엇인지에 대해 컴파일시에 모호성이있는 경우, 컴파일러는 중지됩니다.

    매니페스트 (manifest)의 사본과 함께 당신은 몇 가지 사용할 수 있습니다. 당신은 일반적으로 원하는 주요 것들 중 하나 삭제를 통해 삭제 된 java.lang.Class의이다 :

    class BoundedManifest[T <: Any : Manifest](value: T) {
      val m = manifest[T]
      m.erasure.toString match {
        case "class java.lang.String" => println("String")
        case "double" | "int"  => println("Numeric value.")
        case x => println("WTF is a '%s'?".format(x))
        }
    }
    
    class ImplicitManifest[T <: Any](value: T)(implicit m: Manifest[T]) {
      m.erasure.toString match {
        case "class java.lang.String" => println("String")
        case "double" | "int" => println("Numeric value.")
        case x => println("WTF is a '%s'?".format(x))
      }
    }
    
    new BoundedManifest("Foo Bar!")
    // String 
    new BoundedManifest(5)
    // Numeric value.
    new BoundedManifest(5.2)
    // Numeric value.
    new BoundedManifest(BigDecimal("8.62234525"))
    // WTF is a 'class scala.math.BigDecimal'?
    new ImplicitManifest("Foo Bar!")
    // String 
    new ImplicitManifest(5)
    // Numeric value.
    new ImplicitManifest(5.2)
    // Numeric value.
    new ImplicitManifest(BigDecimal("8.62234525"))
    // WTF is a 'class scala.math.BigDecimal'?
    

    이것은 무슨 일이 일어나고 있는지 다소 불안정한 예를 만 보여줍니다. 나는 스칼라 2.8에 잘 FWIW로 출력이 달렸다.

    를 [T ... : 매니페스트] 경계는 스칼라 2.8에 ... 당신이 암시 적으로 ImplicitManifest에 표시된 매니페스트 잡아해야하는 데 사용되는 새로운 기능입니다. 당신은 실제로 매니페스트의 사본을하지 않습니다. 하지만 발 m = 매니페스트 말하여 코드 내부를 가져올 수 있습니다 [T] ... 매니페스트 [_]는 boundaried 블록 내부의 적절한 매니페스트 유형을 찾을 수 명백히 PREDEF에 정의되어있다.

    <> <와> 당신이 Manifest에서 얻을 다른 두 가지 주요 항목 인 테스트 하위 / 상위 유형 또 다른 대 매니페스트 하나. 내가 올바르게 기억이 현명 아주 순진 구현하고 항상 일치하지 않는하지만 난 몇 가능한 삭제 입력에 대해 테스트를 사용하여 생산 코드의 무리가 있습니다. 다른 매니페스트에 대한 확인의 간단한 예 :

    class BoundedManifestCheck[T <: Any : Manifest](value: T) {
      val m = manifest[T]
      if (m <:< manifest[AnyVal]) {
        println("AnyVal (primitive)")
      } else if (m <:< manifest[AnyRef]) {
        println("AnyRef")
      } else {
        println("Not sure what the base type of manifest '%s' is.".format(m.erasure))
      }
    }
    
    
    new BoundedManifestCheck("Foo Bar!")
    // AnyRef
    new BoundedManifestCheck(5)
    // AnyVal (primitive)
    new BoundedManifestCheck(5.2)    
    // AnyVal (primitive)
    new BoundedManifestCheck(BigDecimal("8.62234525"))
    // AnyRef
    

    호르헤 오티즈이에 좋은 블로그 게시물을 (옛 불구하고) 있습니다 http://www.scala-blogs.org/2008/10/manifests-reified-types.html

    편집하다:

    당신은 실제로 스칼라가 삭제 컴파일러 단계의 결과를 출력하도록 요청함으로써 무엇을하고 있는지 볼 수 있습니다.

    실행, 스칼라 -Xprint 위 내 마지막 예에서 : 삭제 test.scala는 다음과 같은 결과를 생성합니다 :

    final class Main extends java.lang.Object with ScalaObject {
      def this(): object Main = {
        Main.super.this();
        ()
      };
      def main(argv: Array[java.lang.String]): Unit = {
        val args: Array[java.lang.String] = argv;
        {
          final class $anon extends java.lang.Object {
            def this(): anonymous class $anon = {
              $anon.super.this();
              ()
            };
            class BoundedManifestCheck extends java.lang.Object with ScalaObject {
              <paramaccessor> private[this] val value: java.lang.Object = _;
              implicit <paramaccessor> private[this] val evidence$1: scala.reflect.Manifest = _;
              def this($outer: anonymous class $anon, value: java.lang.Object, evidence$1: scala.reflect.Manifest): BoundedManifestCheck = {
                BoundedManifestCheck.super.this();
                ()
              };
              private[this] val m: scala.reflect.Manifest = scala.this.Predef.manifest(BoundedManifestCheck.this.evidence$1);
              <stable> <accessor> def m(): scala.reflect.Manifest = BoundedManifestCheck.this.m;
              if (BoundedManifestCheck.this.m().<:<(scala.this.Predef.manifest(reflect.this.Manifest.AnyVal())))
                scala.this.Predef.println("AnyVal (primitive)")
              else
                if (BoundedManifestCheck.this.m().<:<(scala.this.Predef.manifest(reflect.this.Manifest.Object())))
                  scala.this.Predef.println("AnyRef")
                else
                  scala.this.Predef.println(scala.this.Predef.augmentString("Not sure what the base type of manifest '%s' is.").format(scala.this.Predef.genericWrapArray(Array[java.lang.Object]{BoundedManifestCheck.this.m().erasure()})));
              protected <synthetic> <paramaccessor> val $outer: anonymous class $anon = _;
              <synthetic> <stable> def Main$$anon$BoundedManifestCheck$$$outer(): anonymous class $anon = BoundedManifestCheck.this.$outer
            };
            new BoundedManifestCheck($anon.this, "Foo Bar!", reflect.this.Manifest.classType(classOf[java.lang.String]));
            new BoundedManifestCheck($anon.this, scala.Int.box(5), reflect.this.Manifest.Int());
            new BoundedManifestCheck($anon.this, scala.Double.box(5.2), reflect.this.Manifest.Double());
            new BoundedManifestCheck($anon.this, scala.package.BigDecimal().apply("8.62234525"), reflect.this.Manifest.classType(classOf[scala.math.BigDecimal]))
          };
          {
            new anonymous class $anon();
            ()
          }
        }
      }
    }
    
  2. ==============================

    2.T은 "바인딩 컨텍스트"... : 매니페스트 암시 인수에 대한 문법 설탕입니다 : (암시 적 사람 : 매니페스트 [T]). 따라서 클래스 이미지에 지정된 타입 생성자 인스턴스화 시점에서 그 존재에 걸쳐 생성 된 클래스 인스턴스 컴파일러 발견 / T 파라미터 종류와 그 값을 사용하는 실제 유형 용품 매니페스트 "로 스틱"및 "앵커" 그 T.에 대한 매니페스트에 이미지 [뭔가]의 각 특정 인스턴스

    T은 "바인딩 컨텍스트"... : 매니페스트 암시 인수에 대한 문법 설탕입니다 : (암시 적 사람 : 매니페스트 [T]). 따라서 클래스 이미지에 지정된 타입 생성자 인스턴스화 시점에서 그 존재에 걸쳐 생성 된 클래스 인스턴스 컴파일러 발견 / T 파라미터 종류와 그 값을 사용하는 실제 유형 용품 매니페스트 "로 스틱"및 "앵커" 그 T.에 대한 매니페스트에 이미지 [뭔가]의 각 특정 인스턴스

  3. from https://stackoverflow.com/questions/3587286/how-does-scalas-2-8-manifest-work by cc-by-sa and MIT license