2009-10-18 7 views
126

Est-il possible de faire une comparaison avec le système de correspondance de modèles de Scala? Par exemple:Utilisation d'opérateurs de comparaison dans le système de correspondance de modèles de Scala

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

La deuxième déclaration de cas est illégale, mais je voudrais être en mesure de préciser « quand un est supérieur à ».

+1

Ceci peut également être utilisé pour vérifier si une fonction est vraie, par ex. 'case x if x.size> 2 => ...' – tstenner

+2

La chose importante à comprendre est que les "patterns" à gauche de => operator sont en effet des "patterns". Le 10 dans le premier cas d'expression que vous avez n'est pas le littéral entier. Donc, vous ne pouvez pas effectuer d'opérations (comme> vérifier ou dire que l'application de fonction isOdd (_)) est à gauche. –

Répondre

243

Vous pouvez ajouter un garde, soit une if et une expression booléenne après le motif:

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

Edit: Notez que ceci est plus que superficiellement différente de mettre ifaprès le =>, parce qu'un le motif ne correspondra pas si le garde n'est pas vrai.

+2

Ben, bonne réponse, cela illustre vraiment l'importance du motif de garde. – JeffV

25

En tant que non-réponse à l'esprit de la question, qui a demandé comment incorporer prédicats dans une clause de correspondance, dans ce cas, le prédicat peut être pris en compte avant la match:

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

Maintenant, the documentation for scala.math.Ordering.compare(T, T) promesses seulement que les résultats non égaux seront supérieur à ou inférieur à zéro. Java Comparable#compareTo(T) est spécifié de manière similaire à Scala. Il est conventionnel d'utiliser respectivement 1 et -1 pour les valeurs positive et négative, comme le fait le modèle current implementation de Scala, mais on ne peut pas faire une telle supposition sans risquer que l'implémentation ne change de dessous.

+4

Je ne suis pas sûr si vous suggérez ceci comme une vraie solution, mais je recommanderais fortement contre tout ce qui repose sur une convention ou une hypothèse non documentée. –

+1

Exactement. C'est pourquoi j'ai écrit «on ne peut pas faire une telle supposition sans risque», et j'ai qualifié ma réponse de «non-réponse». Il est intéressant de considérer * pourquoi * 'compare()' et 'compareTo()' ne spécifient pas 0, 1 et -1 comme codomaine. – seh

+4

Math.signum (n compare 10) garantirait -1, 0 ou 1. – richj

15

Une solution qui, à mon avis est beaucoup plus lisible que les gardes en ajoutant:

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

Notes:

  • Ordered.compare retourne un entier négatif si cela est inférieur à celui, positif si plus, et 0 si identique.
  • Int.signum comprime la sortie de compare à -1 pour un nombre négatif (moins de 10), pour 1 positif (supérieur à 10), ou 0 de zéro (égale à 10).