Як реалізується відповідність шаблонів у Scala на рівні байт-коду?


123

Як реалізується відповідність шаблонів у Scala на рівні байт-коду?

Це як серія if (x instanceof Foo)конструкцій чи щось інше? Які її наслідки для продуктивності?

Наприклад, з огляду на наступний код (зі сторінок 46-48 Scala By Example ), як 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? Я замовив книгу, але вона ще не дійшла.


Чому б ви просто не скласти приклад і не розібрати його за допомогою розбірника байтових кодів Java?
Зіфре

Я, мабуть, буду це робити, якщо хтось спочатку не дасть хорошої відповіді. Але зараз я хочу трохи поспати. ;)
Еско Луонтола

27
Питання корисне іншим читачам!
джондаль

1
@djondal: найкращий спосіб сказати, що це просто вирішити питання :-)
Blaisorblade

Відповіді:


96

Низький рівень можна дослідити за допомогою розбиральника, але коротка відповідь полягає в тому, що це купа if / elses, де предикат залежить від шаблону

case Sum(l,r) // instance of check followed by fetching the two arguments and assigning to two variables l and r but see below about custom extractors 
case "hello" // equality check
case _ : Foo // instance of check
case x => // assignment to a fresh variable
case _ => // do nothing, this is the tail else on the if/else

Можна набагато більше, що можна зробити з подібними візерунками або з моделями та комбінаціями на кшталт "case Foo (45, x)", але, як правило, це лише логічні розширення того, що я щойно описав. Візерунки можуть також мати варти, які є додатковими обмеженнями для предикатів. Також є випадки, коли компілятор може оптимізувати відповідність шаблонів, наприклад, коли між випадками є певне перекриття, воно може трохи поєднати речі. Розширені зразки та оптимізація - це активна область роботи в компіляторі, тому не дивуйтеся, якщо байт-код істотно покращиться над цими основними правилами в поточній та майбутніх версіях Scala.

На додаток до всього цього, ви можете написати власні спеціальні екстрактори на додаток до замість тих, що Scala використовує для класів справ. Якщо ви це зробите, то вартість відповідності шаблону - це вартість того, що робить витяжка. Хороший огляд знайдено в http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf


Я вважаю, що це поточне посилання: infoscience.epfl.ch/record/98468/files/…
greenoldman

78

Джеймс (нагорі) сказав це найкраще. Однак якщо вам цікаво, завжди добре вправу подивитися на розібраний байт-код. Ви також можете scalacскористатися -printопцією, яка надрукує вашу програму зі всіма видаленими функціями Scala. Це в основному Java в одязі Scala. Ось відповідний scalac -printвихід для фрагменту коду, який ви дали:

def eval(e: Expr): Int = {
  <synthetic> val temp10: Expr = e;
  if (temp10.$isInstanceOf[Number]())
    temp10.$asInstanceOf[Number]().n()
  else
    if (temp10.$isInstanceOf[Sum]())
      {
        <synthetic> val temp13: Sum = temp10.$asInstanceOf[Sum]();
        Main.this.eval(temp13.e1()).+(Main.this.eval(temp13.e2()))
      }
    else
      throw new MatchError(temp10)
};

34

Починаючи з версії 2.8, Scala має анотацію @switch . Мета полягає в тому, щоб переконатися, що відповідність шаблонів буде зібрана в таблиці перемикача або перемикача, а не в ряд умовних ifоператорів.


6
коли вибрати @switch над звичайним, якщо ще?
Аравінд Яррам

2
використання @switchє більш ефективним, ніж звичайне узгодження шаблонів. тому, якщо всі випадки містять постійні значення, ви завжди повинні використовувати @switch(адже реалізація байт-коду буде такою ж, як у java switchзамість багатьох if-else)
лев
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.