0

スクリプトがあります。警告なしで実行されます。

$ cat ~/tmp/so1.scala 
import org.yaml.snakeyaml.Yaml

class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
  def foreach (f: Tuple2 [K, V] => Unit): Unit = {
    val iter = map.entrySet.iterator
    while (iter.hasNext) {
      val entry = iter.next
      f (entry.getKey, entry.getValue)
    }
  }
}

implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)

val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map [_, _] => {
    for (entry <- map) {
      entry match {
        case ("id", id: String) => System.out.println ("ID is " + id)
        case (n: String, v: String) => System.out.println (n + " = " + v)
      }
    }
  }
}

$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so1.scala eg/default.yaml
(program output as expected)

ループを独自の関数に抽出したいと思います。だから私はそれを試してみます。

$ cat ~/tmp/so2.scala 
import org.yaml.snakeyaml.Yaml

class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
  def foreach (f: Tuple2 [K, V] => Unit): Unit = {
    val iter = map.entrySet.iterator
    while (iter.hasNext) {
      val entry = iter.next
      f (entry.getKey, entry.getValue)
    }
  }
}

implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)

val processMap = (map: java.util.Map [_, _]) => {
  for (entry <- map) {      // line 16
    entry match {
      case ("id", id: String) => System.out.println ("ID is " + id)
      case (n: String, v: String) => System.out.println (n + " = " + v)
    }
  }
}

val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map [_, _] => processMap (map)
}

$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so2.scala eg/default.yaml
(fragment of so2.scala):16: error: type mismatch;
 found   : map.type (with underlying type java.util.Map[_, _])
 required: java.util.Map[_$1,_$2] where type _$2, type _$1
  for (entry <- map) {
                 ^
one error found
!!!
discarding <script preamble>

ループが独自の機能を持っているということは、より具体的なタイプが必要であることを意味します。わかった。

java.util.Map [AnyRef, AnyRef]の代わりに試してみますjava.util.Map [_, _]

$ cat ~/tmp/so3.scala 
import org.yaml.snakeyaml.Yaml

class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
  def foreach (f: Tuple2 [K, V] => Unit): Unit = {
    val iter = map.entrySet.iterator
    while (iter.hasNext) {
      val entry = iter.next
      f (entry.getKey, entry.getValue)
    }
  }
}

implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)

val processMap = (map: java.util.Map [AnyRef, AnyRef]) => {
  for (entry <- map) {
    entry match {
      case ("id", id: String) => System.out.println ("ID is " + id)
      case (n: String, v: String) => System.out.println (n + " = " + v)
    }
  }
}

val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map [AnyRef, AnyRef] => processMap (map)      // line 26
}

$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so3.scala eg/default.yaml
(fragment of so3.scala):26: warning: non variable type-argument AnyRef in type pattern is unchecked since it is eliminated by erasure
  case map: java.util.Map [AnyRef, AnyRef] => processMap (map)
                       ^
one warning found
!!!
discarding <script preamble>
(program output as expected)

これで実行されますが、警告が表示されます。その警告を取り除くにはどうすればよいですか?

ノート:

  1. org.yaml.snakeyaml.YamlはJavaで記述されているため、タイプマニフェストを使用できません。(できますか?)
  2. 私の実際のプログラムはいくつかのJavaライブラリを使用しているので、与えられているタイプについて誤った仮定をする可能性がある場合は警告が必要です。しかし、コンパイラに「はい、これを確認しました。正しいです。再度警告しないでください」とどのように伝えるのでしょうか。
  3. 私はscala2.7.7を使用しています(これはUbuntuにパッケージされているバージョンだからです)。
4

2 に答える 2

3

最初にカスタム ラッパーを削除してみてください。(2.8.1) Scala 標準ライブラリには、Java コレクション型をより慣用的に使用するためのラッパーが既に含まれていますscala.collection.JavaConverters(注:scala.これをインポートする場合、プレフィックスは必要ありません)

processMapまた、関数の代わりにメソッドを作成し、型パラメーターを追加します。

import collection.JavaConverters._

def processMap[K,V](map: Map[K, V]): Unit = {
  for (entry <- map) {
    entry match {
      case ("id", id: String) => System.out.println ("ID is " + id)
      case (n: String, v: String) => System.out.println (n + " = " + v)
    }
  }
}

val yaml = new Yaml
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
  case map: java.util.Map[_, _] => processMap(map.asScala)
}

最後から 2 行目のメソッドに注意してくださいasScala...

Java/Scala の相互運用を扱う場合、通常は、できるだけ早い機会に Java から Scala コレクションに変換し、できるだけ遅く元に戻すことがベスト プラクティスです。

于 2011-03-12T18:13:24.637 に答える
0

Scala 2.7.X を使用している必要があります。2.8.1 を使用する場合、Map[_,_] を使用した例は正常に機能します。

2.7.X を使用する必要がある場合は、processMap の値をメソッドに変換してみてください: def processMap[K,V] = (map: java.util.Map[K,V]) => {...}私のためにコンパイルしますが、YAML ライブラリを使用してパーツを「スタブ化」したことに注意してください。私が使用した:

val m1 = new java.util.HashMap[String,String]
m1.put("one", "1")
m1.put("id", "123")
m1.put("two", "2")

m1 match {
  case map: java.util.Map [_, _] => processMap (map)
}
于 2011-03-12T18:02:59.323 に答える