Подтвердить что ты не робот

Адаптация списка аргументов путем вставки() устарела

Я только что обновляюсь с Scala 2.10.x до 2.11.2, и я получаю следующее предупреждение со следующим кодом:

  override def validateKey(key: String): Either[InvalidKeyError, Unit] = 
    keys.contains(key) match {
      case true => Right()
      case false => Left(InvalidKeyError(context, key))
    }

Адаптация списка аргументов путем вставки() устарела: это вряд ли будет тем, что вы хотите. подпись: Right.apply [A, B] (b: B): scala.util.Right [A, B] данные аргументы: после адаптации: Right ((): Unit)

Я могу решить это, изменив "истинный" оператор case:

case true => Right(()) //() is a shortcut to a Unit instance

Является ли это правильным способом устранения этого предупреждения?

Изменить: возможно, ответ "почему мы должны это делать сейчас" будет подходящим, мое беглое исследование, похоже, указывает на то, что Scala вставка "Единицы", когда он считает, что ему нужно вызвать другие проблемы

4b9b3361

Ответ 1

Автоматический Unit вывод устарел в scala 2.11, и причина этого в том, что это может привести к запутанному поведению, особенно для людей, изучающих язык.

Здесь пример

class Foo[T](value: T)
val x = new Foo

Это не должно компилироваться, не так ли? Вы вызываете конструктор без аргументов, где требуется. Удивительно, но до scala 2.10.4 это компилируется просто отлично, без ошибок или предупреждений.

И это потому, что компилятор вывел аргумент Unit, поэтому он фактически заменил ваш код на

val x = new Foo[Unit](()) // Foo[Unit]

Как говорится в новом предупреждающем сообщении, это вряд ли будет тем, что вы хотите.

Другим известным примером является

scala> List(1,2,3).toSet()
// res1: Boolean = false

вызов toSet() должен быть ошибкой времени компиляции, так как toSet не принимает аргументы, но компилятор отчаянно пытается скомпилировать его, в конечном счете интерпретируя код как

scala> List(1,2,3).toSet.apply(())

что означает: проверить, принадлежит ли () к набору. Поскольку это не так, вы получаете false!

Итак, начиная с scala 2.11, вы должны быть явным, если вы хотите передать () (aka Unit) в качестве аргумента. Вот почему вы должны написать:

Right(())

вместо

Right()

примеры, взятые из Упрощение scala - прошлое, настоящее и будущее Саймона Оксенса.

Ответ 2

Возможно, это должно быть Right(()). Вы пробовали это?

Ответ 3

Мое объяснение состоит в том, что поскольку Right.apply является полиморфным, он может принимать всевозможные параметры, делая Right() означает передачу в Unit, а компилятор просто советует вам, что, возможно, это не то, что вы хотите, Знаю, что это то, чего ты действительно хочешь.

Если вы видите свое отрицательное сообщение, оно сообщает:

... после адаптации: Right ((): Unit)

Это означает, что компилятор автоматически решил, что вы проходите в Unit, так как это похоже на void, ему это действительно не нравится, в частности, передача в Unit как () явно указывает компилятор, который вам нужен, Unit. Во всяком случае кажется новой формой устаревания scala 2.11, я не могу воспроизвести это в 2.10.4.