Как сопоставление с образцом в Scala реализовано на уровне байт-кода?
Это что-то вроде серии if (x instanceof Foo)
конструкций или чего-то еще? Каковы его последствия для производительности?
Например, учитывая следующий код (из Scala By Example, страницы 46-48), как будет eval
выглядеть эквивалентный Java-код для метода?
abstract class Expr
case class Number(n: Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
def eval(e: Expr): Int = e match {
case Number(x) => x
case Sum(l, r) => eval(l) + eval(r)
}
PS Я могу читать байт-код Java, поэтому мне было бы достаточно представления байт-кода, но, вероятно, другим читателям было бы лучше знать, как он будет выглядеть как Java-код.
PPS Дает ли книга « Программирование на Scala» ответ на этот и подобные вопросы о том, как реализована Scala? Я заказал книгу, но она еще не пришла.
performance
scala
pattern-matching
bytecode
Эско Луонтола
источник
источник
Ответы:
Низкий уровень можно изучить с помощью дизассемблера, но краткий ответ заключается в том, что это набор if / elses, где предикат зависит от шаблона.
Вы можете сделать гораздо больше с помощью шаблонов, таких как или шаблоны и комбинации, такие как case Foo (45, x), но в целом это просто логические расширения того, что я только что описал. У шаблонов также могут быть охранники, которые являются дополнительными ограничениями для предикатов. Есть также случаи, когда компилятор может оптимизировать сопоставление с образцом, например, когда есть некоторое перекрытие между случаями, он может немного объединить вещи. Расширенные шаблоны и оптимизация являются активной областью работы в компиляторе, поэтому не удивляйтесь, если байтовый код существенно улучшится по сравнению с этими базовыми правилами в текущей и будущих версиях Scala.
В дополнение ко всему, вы можете написать свои собственные экстракторы в дополнение к тем, которые Scala использует по умолчанию для классов case, или вместо них. Если вы это сделаете, то стоимость сопоставления с образцом будет равна стоимости того, что делает экстрактор. Хороший обзор можно найти в http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf
источник
Джеймс (вверху) сказал это лучше всего. Однако, если вам интересно, всегда полезно посмотреть на дизассемблированный байт-код. Вы также можете вызвать
scalac
эту-print
опцию, которая распечатает вашу программу без всех специфичных для Scala функций. По сути, это Java в одежде Scala. Вот соответствующийscalac -print
результат для предоставленного вами фрагмента кода:источник
Начиная с версии 2.8 в Scala есть аннотация @switch . Цель состоит в том, чтобы гарантировать, что сопоставление шаблонов будет скомпилировано в tablewitch или lookupswitch, а не в серию условных
if
операторов.источник
@switch
более эффективно, чем обычное сопоставление с образцом. поэтому, если все случаи содержат постоянные значения, вы всегда должны использовать@switch
(потому что реализация байт-кода будет такой же, как в java,switch
а не во многих if-else)