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

Я только что обновляюсь с 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 вставка "Единицы", когда он считает, что ему нужно вызвать другие проблемы

Ответ 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.