Как мне избавиться от этого типа предупреждения / ошибки? - PullRequest
0 голосов
/ 12 марта 2011

У меня есть скрипт. Работает без предупреждений.

$ 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. Я использую scala 2.7.7 (потому что это версия, поставляемая с Ubuntu).

Ответы [ 2 ]

3 голосов
/ 12 марта 2011

Вы можете попробовать удалить свою пользовательскую оболочку для начала.Стандартная библиотека Scala (2.8.1) уже содержит оболочку для более простого использования типов коллекций 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)
}

Обратите внимание на метод asScala от второй до последней строки ...

При работе с взаимодействием Java / Scala обычно рекомендуется преобразовать коллекции Java в Scala как можно раньше.возможность, и конвертировать обратно как можно позже.

0 голосов
/ 12 марта 2011

Вы должны использовать 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)
}
...