Как сопоставление с образцом в Scala реализовано на уровне байт-кода?

Как это?

% Input block size.
ibs = 3;

% Input.
input = [ 1 * ones(ibs); 2 * ones(ibs); 3 * ones(ibs); 4 * ones(ibs) ]

% Determine block size. 
bs = size(input, 2);

% Check format.
if (size(input, 1) != 4 * bs)
  disp('Wrong format.');
end

% Transpose input.
input = input.';

% Generate output.
output = [input(1:bs, 1:2*bs); input(1:bs, 2*bs+1:4*bs)]

Вывод:

input =
   1   1   1
   1   1   1
   1   1   1
   2   2   2
   2   2   2
   2   2   2
   3   3   3
   3   3   3
   3   3   3
   4   4   4
   4   4   4
   4   4   4

output =
   1   1   1   2   2   2
   1   1   1   2   2   2
   1   1   1   2   2   2
   3   3   3   4   4   4
   3   3   3   4   4   4
   3   3   3   4   4   4

Я сейчас не удовлетворен. Должно быть лучшее решение для последней строки моего сценария. Любые улучшения приветствуются!

118
задан Peter Mortensen 10 May 2013 в 08:00
поделиться

2 ответа

Низкий уровень можно исследовать с помощью дизассемблера, но краткий ответ таков: это кучка 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

92
ответ дан James Iry 24 November 2019 в 01:58
поделиться

Джеймс (выше) сказал это лучше всего. Однако, если вам интересно, всегда полезно посмотреть на дизассемблированный байт-код. Вы также можете вызвать 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)
};
75
ответ дан Jorge Ortiz 24 November 2019 в 01:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: