2011-07-04 3 views
3

스 카라의 다른 목록을 기반으로 매니페스트를 정의 할 수 있습니까?Scala의 다른 목록을 기반으로 매니페스트를 정의 할 수 있습니까?

저는 스칼라 선언 정보가 동적으로 사용되지 않기 때문에 이것이 가능하지 않다는 믿음을 사퇴했습니다.

여기에 문제가 있습니다. 나는 여러 유형의 객체를 반환 할 수있는 함수를 가지고 있습니다. (String, Int, List [Int], List [List [String]] 등) 이러한 여러 유형을 지원하기 위해 반환 유형은 Any로 설정되었지만 만기가되었습니다. 지우기를 입력하려면 목록,지도 등에서 지원되는 유형에 대한 정보가 손실됩니다. 일부 세부 사항을 복구하기 위해 리턴 유형과 함께 Manifest를 리턴합니다.

그러나 반환 된 정보는 다른 목록이나 맵에 배치 된 다음 다른 함수에서 반환 될 수 있습니다. 유형이 이제는 매니페스트에 정의 된 이전 유형의 목록 또는지도라는 사실을 포함하도록 매니페스트를 업데이트하려고합니다. 여기

내가 V1 유형 목록 [지능]의 것을 알고 'V1'의 매니페스트에서 몇 가지 예제 코드

def returnWithManifest[T: Manifest](x: T) = (x, manifest[T]) 

// May return String, Int, List[Int], List[List[String]], ... 
def contrivedExample(t: String): (Any, Manifest[_]) = t match { 
    case "String" => returnWithManifest("test") 
    case "Int" => returnWithManifest(1) 
    case "Boolean" => returnWithManifest(true) 
    case "List[Int]" => returnWithManifest(List(1,2,3)) 
    case "List[List[String]]" => 
    returnWithManifest(List(List("a","b"),List("c","d"))) 
    case _ => returnWithManifest(None) 
} 

scala> val v1 = contrivedExample("List[Int]") 
v1: (Any, Manifest[_]) = (List(1, 2, 3),scala.collection.immutable.List[Int]) 

scala> val x = v1._1 
x: Any = List(1, 2, 3) 

scala> val m = v1._2 
m: scala.reflect.Manifest[_] = scala.collection.immutable.List[Int] 

scala> val v2 = List(x) 
v2: List[Any] = List(List(1, 2, 3)) 

의 내가 만들 때 내가 만드는 데 필요한 모든 정보를 가지고 있어야 'V2' 그 타입이 List [List [Int]]임을 확인하는 manifest이지만 대신 List [Any] 만 사용하면됩니다. 아마도 다음과 같은 구문 :

val v2: m = List(x) 
val v2 = List[m](x) 

을 나는 동적으로 유형을 정의하기 위해 노력하고있어 것 같습니다 실현, 그러나 실제로 정보가 정적으로 알려진 형식의 삭제를 입력 관련 메타 데이터입니다. 나는 이것이 해결 될 수 있다면, 유형 삭제가 해결 될 수 있다고 생각합니다. 그러나, 적어도 내가 같은 것을 할 수 있어야한다고 생각 :

scala> val m2 = m.wrapInList() 
m2: scala.reflect.Manifest[_] = 
     scala.collection.immutable.List[scala.collection.immutable.List[Int]] 
+0

정말 이상한 디자인을 사용하기 위해 어떤 제약 조건을 요구하는지 알고 싶습니다. – paradigmatic

답변

5

편집 : 아드리안 무어는 바로이 작품을 지적한다 :

def makeListManifest[T: Manifest] = manifest[List[T]] 

당신은 그냥 당신이 얻은 매니페스트를 전달 명시 적으로 호출해야합니다.


내 오랜 답변 : 현재이 자동으로 작동하지 않습니다

huynhjl 부분적 권리입니다. 우리는 컴파일러가 이것을 컴파일하기에 충분히 똑똑해야합니다 :

def makeListManifest[T](m: Manifest[T]) = manifest[List[T]] 

여분의 암시적인 매개 변수없이. 필자는 컴파일러가 필요로하는 모든 정적 유형 정보를 가지고 있다면 manifest가 로컬에 삽입 될 것이라고 믿기 때문에 (아직 필요한 모든 정보가 여기에있다) 확실하게 실현되지만 (2.9.0.1) 아직 구현되지 않았다. 암시 적 범위이지만 다른 (암시 적으로 사용 가능한) 매니페스트에서는 생성되지 않습니다.

scala> import reflect.Manifest 
scala> Manifest.classType(classOf[List[_]], manifest[Int]) 
res0: scala.reflect.Manifest[List[_]] = scala.collection.immutable.List[Int] 

그래서 당신이 makeListManifest 자신을 구현할 수 있습니다 :

할 수있는 일, 그러나, 동반자 개체의 방법으로 자신을 나타내 구조입니다

scala> def makeListManifest[T](m: Manifest[T]) = Manifest.classType(classOf[List[_]], m)    
makeListManifest: [T](m: scala.reflect.Manifest[T])scala.reflect.Manifest[List[_]] 

참고 그 권리 비록 매니페스트가 반환되고 makeListManifest의 정적 반환 유형은 Manifest[List[_]]입니다. 하지만 Manifest[List[T]]으로 안전하게 전송할 수 있습니다.

+0

당신은 단순히 당신의 인자 목록에 암시 적 수정자를 잊어 버린 것 같아요. 이것은 나를 위해 작동합니다 :'def makeListManifest [T : Manifest] = manifest [List [T]]' –

+0

@Adriaan 오, 촬영 - 당신은 물론 옳습니다. –

+0

이 트릭을 할 것입니다, 감사합니다 – Mike

1

함수가 매니페스트 [_]를 반환하기 때문에 내 생각을, 컴파일러는 유형을 복구하는 데 필요한 정보를 잃었다. m이 다른 이야기가 될 Manifest[List[Int]] 유형 인 경우.

+0

true이지만 컴패니언 개체의 메서드를 사용하여 직접 매니페스트를 구성 할 수 있습니다. –

5

스칼라 유형 시스템을 사용하면 Any을 반환하는 것보다 더 잘할 수 있습니다. 타입 공용체 (a.k.a. "분리 유형")를 정의하는 데는 여러 가지 방법이 있습니다. 예 : 당신은 또한 반환 형식에 대한 자신의 ADT를 가질 수 있습니다 물론

이럴 깨끗한 솔루션 :

trait ReturnValue 
case class ReturnInt(value: Int) extends ReturnValue 
case class ReturnString(value: String) extends ReturnValue 
case class ReturnIntList(value: List[Int]) extends ReturnValue 
... 

[편집] 당신이 일치하는 변수들에서 볼 수 있듯이

def otherContrivedExample(t: String or List[Int] or List[List[String]]) = t match { 
    case DisjointType(Some(DisjointType(Some(s),_)), _) => println("processing String: " + s) 
    case DisjointType(Some(DisjointType(_,Some(s))), _) => println("processing List[String]: " + s) 
    case DisjointType(_,Some(s)) => println("processing List[List[Int]]: head=" + s.head) 
} 

val x = contrivedExample("List[List[String]]") 
otherContrivedExample(x) 
//--> processing List[List[Int]]: head=List(a, b) 

: 안전하게 유형을 이제

def contrivedExample(t: String): String or List[Int] or List[List[String]] = t match { 
    case "String" => "test" 
    case "List[Int]" => List(1,2,3) 
    case "List[List[String]]" => List(List("a","b"),List("c","d")) 
} 

우리가 자세하게 검색 할 수 있지만 : 두 번째 링크에서 정의와 함께가는

, 우리는 쓸 수 우리가 언급하지는 않았지만 올바른 유형이 있습니다. 암묵적인 마법 및/또는 특수 추출기를 사용하여 추출 프로세스를 단순화 할 수 있다고 확신합니다.

+0

방법에 대한 반환 형식으로 공용품 유형을 구현하기 위해 귀하의 링크 중 하나에 설명되어있는 것을 사용하는 방법에 대해 좀 더 자세히 설명 할 수 있다면 흥미가 있습니다. –

+0

@ Jean-Philippe Pellet : 제 편집을 참조하십시오. – Landei

+0

고마워요! 패턴 매칭 부분이 너무 장황하다. –

관련 문제