Como a correspondência de padrões no Scala é implementada no nível do bytecode?
É como uma série de if (x instanceof Foo)
construções, ou algo mais? Quais são as implicações de desempenho?
Por exemplo, dado o código a seguir (das páginas 46 a 48 do Scala By Example ), como seria o código Java equivalente para o eval
método?
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: Posso ler bytecode Java, portanto, uma representação de bytecode seria boa o suficiente para mim, mas provavelmente seria melhor para os outros leitores saberem como seria o código Java.
PPS O livro Programming in Scala dá uma resposta a esta e outras perguntas semelhantes sobre como o Scala é implementado? Eu pedi o livro, mas ele ainda não chegou.
performance
scala
pattern-matching
bytecode
Esko Luontola
fonte
fonte
Respostas:
O nível baixo pode ser explorado com um desmontador, mas a resposta curta é que são vários casos em que o predicado depende do padrão
Você pode fazer muito mais com padrões como ou padrões e combinações como "case Foo (45, x)", mas geralmente essas são apenas extensões lógicas do que acabei de descrever. Os padrões também podem ter proteções, que são restrições adicionais nos predicados. Também existem casos em que o compilador pode otimizar a correspondência de padrões, por exemplo, quando há alguma sobreposição entre os casos, ele pode se unir um pouco. Padrões avançados e otimização são uma área ativa de trabalho no compilador; portanto, não se surpreenda se o código de bytes melhorar substancialmente essas regras básicas nas versões atuais e futuras do Scala.
Além de tudo isso, você pode escrever seus próprios extratores personalizados, além dos ou padrão, que o Scala usa para as classes de caso. Se o fizer, o custo da correspondência de padrões é o custo do que quer que o extrator faça. Uma boa visão geral é encontrada em http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf
fonte
James (acima) disse isso melhor. No entanto, se você estiver curioso, é sempre um bom exercício observar o código de código desmontado. Você também pode chamar
scalac
com a-print
opção, que imprimirá seu programa com todos os recursos específicos do Scala removidos. É basicamente Java nas roupas de Scala. Aqui está ascalac -print
saída relevante para o snippet de código que você forneceu:fonte
Desde a versão 2.8, o Scala possui a anotação @switch . O objetivo é garantir que a correspondência de padrões seja compilada no comutador de tabela ou no modo de pesquisa, em vez de uma série de
if
instruções condicionais .fonte
@switch
é mais eficiente que a correspondência regular de padrões. por isso, se todos os casos contêm valores constantes, você deve sempre usar@switch
(porque a implementação bytecode será o mesmo a partir de javaswitch
em vez de muitos if-else)