스칼라의 매니페스트는 무엇이며 언제 필요합니까?


132

스칼라 2.7.2부터는 Manifest자바의 유형 삭제를위한 해결 방법이 있습니다. 그러나 어떻게 Manifest정확하게 작동하며 왜 / 어떻게 사용해야합니까?

Jorge Ortiz 의 블로그 게시물 Manifests : Reified Types 는 그 중 일부를 설명하지만 컨텍스트 범위 와 함께 사용하는 방법에 대해서는 설명하지 않습니다 .

또한, ClassManifest차이점은 Manifest무엇입니까?

유형 삭제와 관련하여 경고가있는 코드 (더 큰 프로그램의 일부, 여기에 쉽게 포함시킬 수 없음)가 있습니다. 매니페스트를 사용하여 이러한 문제를 해결할 수있을 것 같지만 정확히 어떻게 확신 할 수 없습니다.


2
가, 매니페스트 / ClassManifest 차이에 대한 메일 링리스트에 대한 논의되어 볼 수있다 scala-programming-language.1934581.n4.nabble.com/...
Arjan Blokzijl

답변:


197

컴파일러는 JVM 런타임이 쉽게 표현할 수있는 것보다 유형에 대한 자세한 정보를 알고 있습니다. 매니페스트는 컴파일러가 유실 된 유형 정보에 대해 런타임에 코드에 차원 간 메시지를 보내는 방법입니다.

이것은 Kleptonian이 어떻게 화석 기록과 인간의 "정크"DNA에 메시지를 남긴 방식과 비슷합니다. 광속 및 중력 공명 필드의 한계로 인해 직접 통신 할 수 없습니다. 그러나 신호에 맞추는 방법을 알고 있다면 점심 식사를 위해 무엇을 먹을지 또는 어떤 로또를 먹을지 결정하는 것에서 상상할 수없는 방식으로 이익을 얻을 수 있습니다.

매니페스트가 자세한 내용을 알지 못하고 현재보고있는 오류에 도움이 될지 확실하지 않습니다.

매니페스트의 일반적인 용도 중 하나는 정적 유형의 컬렉션에 따라 코드가 다르게 동작하는 것입니다. 예를 들어, List [String]을 다른 유형의 List와 다르게 취급하려면 다음을 수행하십시오.

 def foo[T](x: List[T])(implicit m: Manifest[T]) = {
    if (m <:< manifest[String])
      println("Hey, this list is full of strings")
    else
      println("Non-stringy list")
  }

  foo(List("one", "two")) // Hey, this list is full of strings
  foo(List(1, 2)) // Non-stringy list
  foo(List("one", 2)) // Non-stringy list

이것에 대한 반영 기반 솔루션에는 아마도 목록의 각 요소를 검사하는 것이 필요할 것입니다.

컨텍스트 바운드는 스칼라에서 유형 클래스를 사용하는 데 가장 적합하며 Debasish Ghosh에서 잘 설명합니다. http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html

컨텍스트 바운드는 메소드 서명을 더 읽기 쉽게 만들 수도 있습니다. 예를 들어, 위의 함수는 다음과 같이 컨텍스트 바운드를 사용하여 다시 작성할 수 있습니다.

  def foo[T: Manifest](x: List[T]) = {
    if (manifest[T] <:< manifest[String])
      println("Hey, this list is full of strings")
    else
      println("Non-stringy list")
  }

25

의 차이에 관한 아니 완전한 답변 만 Manifest하고 ClassManifest, 당신의 예를 찾을 수 있습니다 스칼라 2.8 Array종이 :

남아있는 유일한 질문은 일반 배열 생성을 구현하는 방법입니다. 자바와는 달리, 스칼라는 인스턴스 생성 새로운 수 있습니다 유형 매개 변수입니다. Java에 균일 한 배열 표현이 없다는 것을 감안할 때 어떻게 구현할 수 있습니까? Array[T]T

이를 수행하는 유일한 방법은 유형을 설명하는 추가 런타임 정보가 필요합니다 T. Scala 2.8에는이를위한 새로운 메커니즘이 있으며이를 매니페스트 라고합니다 . 유형의 객체는 유형에 Manifest[T]대한 완전한 정보를 제공합니다 T.
Manifest값은 일반적으로 암시 적 매개 변수로 전달됩니다. 그리고 컴파일러는 정적으로 알려진 유형에 대해 구성하는 방법을 알고 있습니다 T.

또한 모든 인수 유형을 알 필요없이 유형의 최상위 클래스 만 알고 구성 할 수 있는 약한 형식의 이름 도 ClassManifest있습니다 .
이 유형의 런타임 정보는 배열 작성에 필요합니다.

예:

ClassManifest[T]메소드에 암시 적 매개 변수로 를 전달하여이 정보를 제공해야합니다 .

def  tabulate[T](len:Int,  f:Int=>T)(implicit m:ClassManifest[T]) =  { 
  val  xs  =  new  Array[T](len) 
  for   (i  <- 0  until   len)  xs(i)   = f(i) 
  xs 
} 

속기 형식으로 컨텍스트 바운드 1을 type 매개 변수에 T대신 사용할 수 있습니다 .

(예를 들어이 SO 질문을 참조하십시오 )

, 기부:

def  tabulate[T:    ClassManifest](len:Int,  f:Int=>T)  =  { 
  val  xs  =  new  Array[T](len) 
  for   (i  <- 0  until   len)  xs(i)   = f(i) 
  xs 
} 

Scala 컴파일러는 Int, 또는 String, 또는 과 같은 형식에서 tabulate를 호출 할 때 테이블 형식에 대한 List[T]암시 적 인수로 전달할 클래스 매니페스트를 만들 수 있습니다.


25

매니페스트는 JVM에서 실행되도록 유형이 지워진 제네릭 형식 (제네릭을 지원하지 않는)을 수정하기위한 것입니다. 그러나 몇 가지 심각한 문제가있었습니다. 너무 단순해서 스칼라 타입 시스템을 완전히 지원할 수 없었습니다. 따라서 Scala 2.10에서는 더 이상 사용되지 않으며TypeTag s (기본적으로 Scala 컴파일러 자체가 유형을 나타 내기 위해 사용하므로 Scala 유형을 완전히 지원함) 로 대체되었습니다 . 차이점에 대한 자세한 내용은 다음을 참조하십시오.

다시 말해

언제 필요합니까?

2013-01-04 이전에 Scala 2.10이 출시되었습니다 .


스칼라 반사는 여전히 2.10에서 실험 중이므로 아직 더 이상 사용되지 않습니다 (그러나 앞으로도 계속 될 것입니다).
Keros

2013-01-04 이전 또는 API를 사용하는 경우
David Moles

1

의는 밖으로 CHCK하자 manifestscala소스 ( Manifest.scala), 우리는 다음을 참조하십시오

Manifest.scala:
def manifest[T](implicit m: Manifest[T])           = m

따라서 다음 예제 코드와 관련하여

def foo[A](somelist: List[A])(implicit m: Manifest[A]): String = {
  if (m <:< manifest[String]) {
    "its a string"
  } else {
    "its not a string"
  }
}

우리는 예제 코드에서 제공 한 것을 만족시키는 manifest function암시 적 검색을 보았습니다 . 따라서 다음과 같이 전화하면m: Manifest[T]type parametermanifest[String]

if (m <:< manifest[String]) {

implicit m함수에서 정의한 전류 가 유형인지 확인 manifest[String]하고 유형 manifest의 함수로 manifest[T]특정 항목을 검색 manifest[String]하여 암시 적 여부를 찾습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.