2012-11-18 2 views
2

Je suis nouveau à Scala, et essayait de comprendre le match.Scala match variable passant

Lorsque je tente d'exécuter le code suivant, la javaw VM ne répond pas (fait attendre pour toujours - d'essayer ce d'éclipse)

case GenericProfile(user) => processGenericProfile(_) 
case _ => println("Invalid data found") 

Cependant, la section suivante fonctionne très bien:

case GenericProfile(user) => processGenericProfile(GenericProfile(user)) 
case _ => println("Invalid data found") 

J'essaie de comprendre pourquoi le premier scénario ne répondrait pas. Je ne veux pas passer GenericProfile (utilisateur) - Je voudrais savoir comment cela peut être simplifié. Thnaks !!

Répondre

8

sans voir comment processGenericProfile et GenericProfile sont définis, il est difficile de dire à coup sûr, mais je pense que votre premier cas (case GenericProfile(user) => processGenericProfile(_)) est tout simplement retourner une fonction partiellement appliquée processGenericProfile et ne pas l'appliquer aux résultats sur la main gauche de l'affaire que je comprends que vous voulez faire ...

Tenir compte de ces séances REPL, où je donne des définitions de « faux » pour processGenericProfile et GenericProfile

scala> case class GenericProfile(user: String) 
defined class GenericProfile 

scala> def processGenericProfile(u: GenericProfile) = "processed" 
processGenericProfile: (u: GenericProfile)java.lang.String 

scala> GenericProfile("Paolo") match { 
    | case GenericProfile(user) => processGenericProfile(_) 
    | case _ => "wrong" 
    | } 
res0: java.lang.Object = <function1> 

voir le type de retour de la match? Il est probable que vous n'êtes pas bloqué, le match renvoie une fonction et ne l'applique pas, alors vous attendez que quelque chose se passe, mais Scala pense qu'il a déjà fait ce que vous vouliez faire (retourner une fonction).

Si vous devez capturer toute GenericProfile, au lieu de simplement l'utilisateur qu'il contient, vous pouvez use an alias avec le symbole @, comme ceci:

scala> GenericProfile("Paolo") match { 
     | case u @ GenericProfile(user) => processGenericProfile(u) 
     | case _ => "wrong" 
     | } 
    res2: java.lang.String = processed 

Une dernière chose. Je ne suis pas sûr de ce que le "utilisateur" dans case GenericProfile(user) représente. La façon dont je l'ai écrit, c'est un nom qui est lié à la valeur contenue dans le GenericProfile. C'est à dire. dans le premier cas, nous disons "si l'article que nous vérifions est un GenericProfile, prenez la chaîne qu'il contient (" Paolo "dans ce cas) et liez-le à un nom user

Puisque vous n'utilisez pas cette valeur sur la droite, vous pouvez également faire:

case u @ GenericProfile(_) => processGenericProfile(u) 

où le _ sur le côté gauche rend explicite que vous l'utilisateur correspondant jeter et vous êtes simplement intéressé à vérifier que la type est un GenericProfile

Si à la place "user" est une variable que vous avez définie précédemment (ie voulez que votre déclaration de cas vérifie que vous avez un GenericProfile pour un utilisateur spécifique), alors vous devez dire à scala que user est quelque chose que vous avez défini et non un nom que vous voulez lier à tout ce qui se trouve dans GenericProfile. Cela peut être fait par surrounding your identifier (user) with backticks, comme ceci:

val user="Paolo" 

GenericProfile("Paolo") match { 
    case u @ GenericProfile(`user`) => processGenericProfile(u) 
               //now this only matches      
               //GenericProfile("Paolo") 
    case GenericProfile(_) => "not Paolo"  
    case _ => "wrong" 
} 
+0

Vous aviez raison - j'utilisais sans le savoir une fonction partielle. Merci pour la réponse détaillée - Inspirant !! – felixmd