Scala'da desen eşleştirme bayt kodu seviyesinde nasıl uygulanır?


123

Scala'da desen eşleştirme bayt kodu seviyesinde nasıl uygulanır?

Bir dizi if (x instanceof Foo)yapı gibi mi yoksa başka bir şey mi? Performansa etkileri nelerdir?

Örneğin, aşağıdaki kod verildiğinde ( Scala By Example sayfalarından 46-48), evalyöntemin eşdeğer Java kodu nasıl görünür?

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)
}

Not: Java bayt kodunu okuyabiliyorum, bu nedenle bir bayt kodu gösterimi benim için yeterince iyi olurdu, ancak muhtemelen diğer okuyucular için bunun Java kodu olarak nasıl görüneceğini bilmesi daha iyi olurdu.

PPS Scala'da Programlama kitabı bu ve Scala'nın nasıl uygulandığına dair benzer sorulara cevap veriyor mu? Kitabı sipariş ettim ama henüz elime ulaşmadı.


Neden örneği derleyip bir Java bayt kodu çözücü ile parçalarına ayırmıyorsunuz?
Zifre

Birisi önce iyi bir cevap vermedikçe muhtemelen bunu yapacağım. Ama şu anda biraz uyumak istiyorum. ;)
Esko Luontola

27
Soru diğer okuyucular için yararlıdır!
djondal

1
@djondal: Bunu söylemenin en iyi yolu soruya
olumlu oy vermektir

Yanıtlar:


96

Düşük seviye bir demonte edici ile keşfedilebilir, ancak kısa cevap, yüklemin modele bağlı olduğu bir grup if / elses olmasıdır.

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)" gibi kalıplar ve kombinasyonlarla yapabileceğiniz daha çok şey var, ama genellikle bunlar az önce anlattığım şeyin mantıksal uzantılarıdır. Modeller, yüklemler üzerinde ek kısıtlamalar olan korumalara da sahip olabilir. Derleyicinin desen eşleştirmesini optimize edebileceği durumlar da vardır, örneğin durumlar arasında bir miktar örtüşme olduğunda, işleri biraz birleştirebilir. Gelişmiş kalıplar ve optimizasyon, derleyicideki aktif bir çalışma alanıdır, bu nedenle, Scala'nın mevcut ve gelecekteki sürümlerinde bayt kodu bu temel kurallara göre önemli ölçüde gelişirse şaşırmayın.

Tüm bunlara ek olarak, Scala'nın vaka sınıfları için kullandığı varsayılanlara ek olarak veya bunların yerine kendi özel çıkarıcılarınızı yazabilirsiniz. Bunu yaparsanız, desen eşleşmesinin maliyeti, çıkarıcının yaptığı şeyin maliyetidir. İyi bir genel bakış http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf adresinde bulunabilir.


Bunun şu anki bağlantı olduğuna inanıyorum: infoscience.epfl.ch/record/98468/files/…
greenoldman

78

James (yukarıda) bunu en iyi şekilde söyledi. Bununla birlikte, merak ediyorsanız, demonte edilmiş bayt koduna bakmak her zaman iyi bir egzersizdir. Ayrıca çağırabileceği scalacile -printtüm Scala özgü kaldırılır özellikleri ile programı yazdırır hangi seçeneği. Temelde Scala'nın giysisindeki Java. scalac -printVerdiğiniz kod parçacığı için alakalı çıktı:

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 sürümünden bu yana, Scala @switch açıklamasına sahip. Amaç, model eşlemesinin koşullu ifadeler dizisi yerine tablo anahtarı veya arama anahtarı olarak derlenmesini sağlamaktır if.


6
Aksi takdirde normal yerine @ switch ne zaman seçilir?
Aravind Yarram

2
kullanmak @switch, normal desen eşleştirmesinden daha etkilidir. bu nedenle, tüm vakalar sabit değerler içeriyorsa, her zaman kullanmalısınız @switch(çünkü bayt kodu uygulaması switch, birçok if-else yerine java ile aynı olacaktır )
lev
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.