2009-10-18 15 views
126

Czy można dopasować porównanie przy użyciu systemu dopasowywania wzorców w Scali? Na przykład:Korzystanie z operatorów porównania w systemie dopasowania wzorców Scala

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

Drugi case jest nielegalne, ale chciałbym być w stanie określić „gdy jest większy niż”.

+1

Można tego również użyć do sprawdzenia, czy funkcja jest prawdziwa, np. 'case x if x.size> 2 => ...' – tstenner

+2

Ważne jest, aby zrozumieć, że "wzorce" po lewej stronie operatora => są rzeczywiście "wzorcami". 10 w pierwszym przypadku, jakie masz, NIE jest literałem całkowitym. Tak więc, nie możesz wykonywać operacji (np.> Sprawdź lub powiedz, że aplikacja funkcji isOdd (_)) po lewej stronie. –

Odpowiedz

243

Możesz dodać strażnika, co oznacza if i logicznej wypowiedzi na wzór:

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

Edycja: Należy pamiętać, że jest to więcej niż powierzchownie różni się położyć ifpo=>, ponieważ wzorzec nie będzie zgodny z, jeśli wartownik nie jest prawdziwy.

+2

Ben, dobra odpowiedź, to naprawdę ilustruje znaczenie wzoru straży. – JeffV

25

Jako braku odpowiedzi na duchu na pytanie, który zapytał, jak włączyć predykaty do klauzuli meczu, w tym przypadku orzeczenie może zostać uwzględniony z przed match:

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

Teraz tylko the documentation for scala.math.Ordering.compare(T, T) obietnice że nierówne wyniki będą większe niż większe niż lub mniejsze niż zero. Java's Comparable#compareTo(T) jest określona podobnie jak Scala. Zwykle używa się wartości 1 i -1 dla wartości dodatniej i ujemnej, odpowiednio, jak ma Scala current implementation, ale nie można założyć takiego założenia bez ryzyka zmiany implementacji od dołu.

+4

Nie jestem pewien, czy sugerujesz to jako prawdziwe rozwiązanie, ale zdecydowanie zaleciłbym przeciw wszystkim, co opiera się na nieudokumentowanej konwencji lub założeniu. –

+1

Dokładnie. Dlatego napisałem "nie można założyć takiego założenia bez ryzyka" i zakwalifikowałem moją odpowiedź jako "brak odpowiedzi". Interesujące jest rozważenie * dlaczego * 'compare()' i 'compareTo()' nie określają 0, 1 i -1 jako ich kodomain. – seh

+4

Math.signum (n porównanie 10) gwarantowałoby -1, 0 lub 1. – richj

15

Rozwiązanie, które moim zdaniem jest o wiele bardziej czytelny niż dodawanie strażników:

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

Uwagi:

  • Ordered.compare zwraca ujemną liczbę całkowitą, jeśli jest to mniej niż to, pozytywny, jeżeli większa, a 0 jeśli jest równa.
  • Int.signum kompresuje dane wyjściowe compare do -1 dla szeregu negatywnych (mniej niż 10), 1 pozytywnej (większe niż 10), albo na wartość zero (0 równą 10).
Powiązane problemy