Scala model eşleştirme sisteminde karşılaştırma operatörlerini kullanma


148

Scala'daki desen eşleme sistemini kullanarak bir karşılaştırma yapmak mümkün mü? Örneğin:

a match {
    case 10 => println("ten")
    case _ > 10 => println("greater than ten")
    case _ => println("less than ten")
}

İkinci vaka bildirimi yasadışı, ancak "a daha büyük olduğunda" belirtebilmek istiyorum.


1
Bu, bir işlevin doğru olarak değerlendirilip değerlendirilmediğini kontrol etmek için de kullanılabilir, örn.case x if x.size > 2 => ...
tstenner

2
Anlaşılması gereken önemli şey, => operatörünün solundaki "kalıpların" gerçekten de "kalıplar" olmasıdır. Sahip olduğunuz ilk durum ifadesindeki 10 tam sayı DEĞİLDİR. Bu nedenle, solda işlem yapamazsınız (>> kontrol edin veya işlev uygulaması isOdd (_) işlevini söyleyin).
Ustaman Sangat

Yanıtlar:


292

ifKalıptan sonra bir koruma, yani bir ve bir boole ifadesi ekleyebilirsiniz :

a match {
    case 10 => println("ten")
    case x if x > 10 => println("greater than ten")
    case _ => println("less than ten")
}

Düzenleme: Bu daha çok yüzeysel bir koyarak farklıdır Not olduğunu if sonra=> bir desen, çünkü olmayacak bekçi doğru değilse eşleşir.


3
Ben, iyi cevap, gerçekten desen korumanın önemini göstermektedir.
JeffV

32

Tahminleri bir maç maddesine nasıl dahil edeceğini soran sorunun ruhuna bir cevap olarak, bu durumda yüklem aşağıdakilerden önce hesaba katılabilir match:

def assess(n: Int) {
  println(
    n compare 10 match {
      case 0 => "ten"
      case 1 => "greater than ten"
      case -1 => "less than ten"
    })
}

Şimdi, dokümantasyonscala.math.Ordering.compare(T, T) sadece eşit olmayan sonuçların sıfırdan büyük veya küçük olacağına dair söz vermektedir . Java'lar Comparable#compareTo(T)Scala'nınkine benzer şekilde belirtilir. Scala'nın şu anki uygulamasında olduğu gibi, sırasıyla pozitif ve negatif değerler için 1 ve -1'i kullanmak gelenekseldir , ancak uygulamanın altında bir değişiklik yapma riski olmadan böyle bir varsayım yapılamaz.


5
Bunu gerçek bir çözüm olarak önerdiğinizden emin değilim, ancak belgelenmemiş bir konvansiyona veya varsayımlara dayanan herhangi bir şeye karşı şiddetle tavsiye ederim.
Ben James

1
Kesinlikle. Bu yüzden "hiç kimse risk almadan böyle bir varsayımda bulunamaz" yazdım ve cevabımı "cevapsız" olarak nitelendirdim. Bu dikkate almak ilginç niçin compare() ve compareTo()0, 1 ve -1 onların değer kümesi olarak belirtmez.
seh

4
Math.signum (n karşılaştırmak 10) -1, 0 veya 1'i garanti eder.
richj

1
Bu sabah , orijinal cevabımı yazdıktan yaklaşık altı yıl sonra, söz konusu uygulamanın bir türden diğerine taşınmasına rağmen, Scala hala -1, 0 veya 1 döndürme davranışını not etti.
seh

2
Geçerli bir cevap, ama şahsen bunu sevmiyorum. 0,1 ve -1'in ne anlama geldiğini unutmak çok kolay.
DanGordon

21

Bence koruma eklemek yerine çok daha okunabilir bir çözüm:

(n compare 10).signum match {
    case -1 => "less than ten"
    case  0 => "ten"
    case  1 => "greater than ten"
}

Notlar:

  • Ordered.comparebundan küçükse negatif, tamsa pozitif ve 0eşitse , tamsayı döndürür .
  • Int.signumçıktısını sıkıştırır compareiçin -1negatif bir sayı (10'dan az) için, 1pozitif için (10'dan büyük) ya da 0sıfır için (10 eşit).

1

Yukarıdaki ve körüklü yanıtların tümü orijinal soruyu mükemmel bir şekilde cevaplasa da, https://docs.scala-lang.org/tour/pattern-matching.html belgelerinde bazı ek bilgiler bulunabilir , bunlar benim durumuma uymadılar ancak bu yığın akışı cevabı Google'daki ilk öneri olduğundan, yukarıdaki sorunun köşe örneği olan cevabımı göndermek istiyorum.
Sorum şu:

  • Bir görev argümanı ile maç ifadesinde bir koruma nasıl kullanılır?

Hangi başka kelimelerle ifade edilebilir:

  • Eşleşme ifadesinde bir işlev argümanı ile bir if ifadesi nasıl kullanılır?

Cevap aşağıdaki kod örneğidir:

    def drop[A](l: List[A], n: Int): List[A] = l match {
      case Nil => sys.error("drop on empty list")
      case xs if n <= 0 => xs
      case _ :: xs => drop(xs, n-1)
    }

scala fiddle bağlantısı: https://scalafiddle.io/sf/G37THif/2case xs if n <= 0 => xs ifadesini görebileceğiniz gibi guard (if) ifadesiyle n (bir işlev argümanı) kullanabiliyor.

Umarım bu benim gibi birine yardımcı olur.

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.