Могу ли я использовать @switch и Enumerations?

Могу ли я использовать switch-case для сопоставления с образцом в перечислениях?

Я старался

import scala.annotation.switch

object Foo extends Enumeration {
  val First = Value
  val Second = Value
  val Third = Value
}

object Main {
  def foo(x: Foo.Value) = (x: @switch) match {
    case Foo.First => 1
    case Foo.Second => 2
    case Foo.Third => 3
  }
}

но получите следующее предупреждение (Scala 2.11.4):

warning: could not emit switch for @switch annotated match
  def foo(x: Foo.Value) = (x: @switch) match {

Затем я попытался вместо этого определить перечисление в Java, поскольку enum в Java отличаются от Enumeration в Scala. Все равно не повезло.

Это @switch сопоставление с образцом доступно только для примитивных типов?


person Paul Draper    schedule 05.01.2015    source источник


Ответы (2)


Чтобы завершить ответ Regis, в Scala In Depth Джошуа Суэрет утверждает, что для Scala должны быть выполнены следующие условия для применения оптимизации tableswitch:

  1. Соответствующее значение должно быть известным целым числом.
  2. Соответствующее выражение должно быть «простым». Он не может содержать никаких проверок типов, операторов if или экстракторов.
  3. Значение выражения также должно быть доступно во время компиляции.
  4. Операторов case должно быть более двух.

Объект Foo не соответствует ни одному из вышеперечисленных критериев, хотя и не подлежит оптимизации tableswitch.

person Nami    schedule 25.01.2015

Смысл аннотации switch состоит в том, чтобы убедиться, что ваше совпадение скомпилировано в инструкцию JVM tableswitch или lookupswitch. Эти инструкции работают только с целыми числами, а это означает, что аннотация switch будет иметь какое-либо влияние только на типы, которые могут безопасно поместиться в Int. Значение самого Int, а также Char, Byte, Short и Boolean. Кроме того, значения, с которыми вы сопоставляетесь, должны быть буквальными значениями (в отличие от значений, хранящихся в val). Учитывая, что Enumeration является эталонным значением, они несовместимы с аннотацией switch. Ограничение литеральных значений на самом деле означает, что, вероятно, нет способа использовать эту эннотацию для Short и Byte по чисто синтаксическим причинам, поскольку в scala нет поддержки литеральных шорт и байтов: вы должны использовать литерал int вместе с типом описание как в 123: Byte, но это не принимается за образец. Таким образом, в качестве допустимых типов остаются только Int, Char и Boolean (полезность использования @switch для логического значения по меньшей мере сомнительна)

person Régis Jean-Gilles    schedule 05.01.2015
comment
Хотя случай переключения Java в перечислении приводит к tableswitch / lookupswitch. Но да, похоже, мои варианты: (1) написать Java или (2), как вы сказали, использовать примитивный тип. - person Paul Draper; 05.01.2015
comment
Важным отличием здесь является то, что перечисления Java имеют встроенную языковую поддержку, в то время как перечисления Scala полностью определены в стандартной библиотеке. - person Régis Jean-Gilles; 05.01.2015