3

新しい2.10リリースに関するScalaの(ややまばらな?)ドキュメントを掘り下げるのに問題があります。型情報のないソースから再帰的にデータを読み取っている状況があります。読んだ時点で、予想されるタイプがわかっているので、そのタイプが受信データと一致しているかどうかを確認できます。

私の問題は次のとおりです。型パラメーター(たとえば、Array[Int])を使用してコレクションオブジェクトを取得しようとする場合、予期される型を使用して、読み取られた値が正しい型であることを確認するにはどうすればよいですか?

これまで、型パラメーターを抽出できるScalaApiによって提供されるコードをいじくり回してきました。また、クラスタグと、それらを使用して配列を作成する方法についても読みました。したがって、私の次の考えは、1)型パラメーターを見つけ、2)その型から配列を作成し、3)読み取られたデータが例外なく適合するかどうかを確認することでした。

val paramType = paramInfo[Array[X]]  // Step 1: Find the X type parameter
val array     = Array[paramType](size) // Step 2: Can't use TypeTags#Type as a normal Java type...
// Step 3: Feed data into the array and hope for the best
// Step 4: Profit!

上記paramTypeは私にタイプを与えるので、それはそのタイプをクラスタグに変換するという単純な問題であるはずです。しかし、その答えは私を暗示しています。

正直なところ、この解決策は私には少し厄介に思えますが、私はこれ以上賢いことを理解することができませんでした。別の解決策があれば、私はすべての耳です!

前もって感謝します。

編集:明確にするために、上記の例は、Array [Int]からタイプXを抽出し(たとえば)、その特定のタイプを含む配列のインスタンスを作成することを示しているはずです。それがより明確になったことを願っています。

編集:おそらく、さらに明確にする必要があります(私は本当にそれを不明確にしましたか?:-))。データソースからコレクションを読み取りたい。そして、私はそのコレクションが正しい、期待されるタイプでタイプされることを望みます。それで、私がメソッドを呼び出したとしましょうreadData。期待するタイプがわかっているので、その期待されるタイプのタイプパラメーターを指定します。例として、Array[Int]としましょう。Array[String]またはIterable[Any]、あるいは単にNullなどです。いつreadDataメソッドが呼び出されました。指定された予想される型(Array [Int])を、外部ソースから読み取られたデータの型と一致させたいと思います。見つかったタイプが期待されるタイプと同じタイプ(またはサブタイプ)である場合、データをキャストして返すことができます。そうでない場合は、例外がスローされ、見つかったデータが予期されたタイプではなかったことをユーザーに通知します。要約すると、どうすればreadData[Array[Int]]仕事に電話をかけることができますか?

編集:Array [Any]を作成し、期待される型(上記のX)を取得し、配列を反復して、要素がXと同じ型(またはサブ型)であるかどうかを確認することで問題を解決しました。 Array[X]にキャストします。以下の例では、予想されるタイプはEで表されています。これはかなりハックですが、繰り返しになりますが、代替案を確認したいと思います...

// Matches if the type of o corresponds (<:<) to the type of x
def verifyType(o : Any, x : Type) : Boolean = { ... } 

// Get the type of the array parameter (X)
val tpe = reflect.runtime.universe.typeOf[E] tpe match {  
  // The returned Type is not an instance of universe.Type - hence the cast              
  case TypeRef(_, _, args) => args.asInstanceOf[List[Type]] 
  case _ => throw new IllegalArgumentException("Could not find type parameters in type " + tpe)
} 

// Iterate the array and make sure the types match
val hasWrongType = array.exists(e => !verifyType(e, tpe))

if (hasWrongType) throw new Exception(...) // The types does not fit
else array.asInstanceOf[E] // We can safely cast
4

1 に答える 1

5

これを行うために Scala 2.10 で新しいものを実際に必要とするわけではありませんが、以前のバージョンの代わりに、次ClassManifestの置換を使用しますClassTag

def makeArray[T : reflect.ClassTag](length: Int): Array[T] = {
  val tTag = implicitly[reflect.ClassTag[T]]
  tTag.newArray(length)
}

REPL では:

scala> makeArray[String](5)
res0: Array[String] = Array(null, null, null, null, null)

プリミティブ型の場合:

scala> makeArray[Int](5)
res1: Array[Int] = Array(0, 0, 0, 0, 0)

編集:2つ取ります:

def makeArrayLike(a: Array[_], length: Int): Array[_] = {
  val cA = a.getClass
  val cC = cA.getComponentType
  java.lang.reflect.Array.newInstance(cC, length).asInstanceOf[Array[_]]
}

REPL では:

scala> val ai1 = Array[Int](1, 2, 3)
ai1: Array[Int] = Array(1, 2, 3)

scala> val as1 = Array[String]("one", "two", "three")
as1: Array[String] = Array(one, two, three)

scala> makeArrayLike(as1, 5)
res0: Array[_] = Array(null, null, null, null, null)

scala> makeArrayLike(ai1, 5)
res1: Array[_] = Array(0, 0, 0, 0, 0)
于 2013-02-01T01:45:12.160 に答える