У меня есть скрипт. Работает без предупреждений.
$ 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)
Так что теперь он работает, но он дает мне предупреждение. Как я могу устранить это предупреждение?
Примечания:
- org.yaml.snakeyaml. Yaml написан на Java, поэтому я не могу использовать манифесты типов. (Могу ли я?)
- Моя настоящая программа использует несколько библиотек Java, поэтому я хочу, чтобы меня предупреждали, когда я делаю ложные предположения о том, какие типы
Мне дают Но как мне сказать компилятору: «Да, я проверил это, это правильно, не предупреждайте меня об этом снова»?
- Я использую scala 2.7.7 (потому что это версия, поставляемая с Ubuntu).