web-dev-qa-db-fra.com

Existe-t-il un moyen plus propre de faire correspondre les motifs dans les fonctions anonymes Scala?

Je me retrouve à écrire du code comme celui-ci:

val b = a map (entry =>
    entry match {
        case ((x,y), u) => ((y,x), u)
    }
)

Je voudrais l'écrire différemment, si cela fonctionnait:

val c = a map (((x,y) -> u) =>
    (y,x) -> u
)

Existe-t-il un moyen de me rapprocher de quelque chose?

36
Owen

Croyez-le ou non, cela fonctionne:

val b = List(1, 2)
b map {
  case 1 => "one"
  case 2 => "two"
}

Vous pouvez ignorer le p => p match dans des cas simples. Cela devrait donc fonctionner:

val c = a map {
  case ((x,y) -> u) => (y,x) -> u
}
56
sblundy

Dans votre exemple, il y a peut-être trois sémantiques subtilement différentes.

  1. Carte sur la collection, transformant chaque élément qui correspond à un motif. Lance une exception si un élément ne correspond pas. Cette sémantique est réalisée avec

    val b = a map { case ((x, y), u) => ((y, x), u) }
    
  2. Carte sur la collection, transformant chaque élément qui correspond à un motif. Jeter silencieusement les éléments qui ne correspondent pas:

    val b = a collect { case ((x, y), u) => ((y, x), u) }
    
  3. Cartographiez la collection, déstructurez en toute sécurité puis transformez chaque élément. Ce sont les sémantiques que j'attendrais pour une expression comme

    val b = a map (((x, y), u) => ((y, x), u)))  
    

    Malheureusement, il n'y a pas de syntaxe concise pour réaliser ces sémantiques dans Scala. Au lieu de cela, vous devez vous déstructurer:

    val b = a map { p => ((p._1._2, p._1._1), p._2) }
    

    On pourrait être tenté d'utiliser une définition de valeur pour la déstructuration:

    val b = a map { p => val ((x,y), u) = p; ((y, x), u) }
    

    Cependant, cette version n'est pas plus sûre que celle qui utilise la correspondance explicite de modèles . Pour cette raison, si vous voulez une sémantique de déstructuration sûre, la solution la plus concise consiste à taper explicitement votre collection pour empêcher un élargissement involontaire et utiliser une correspondance de modèle explicite:

    val a: List[((Int, Int), Int)] = // ...
    // ...
    val b = a map { case ((x, y), u) => ((y, x), u) }
    

    Si la définition de a apparaît loin de son utilisation (par exemple dans une unité de compilation séparée), vous pouvez minimiser le risque en attribuant son type dans l'appel de carte:

    val b = (a: List[((Int, Int), Int)]) map { case ((x, y), u) => ((y, x), u) }
    
22
Aaron Novstrup

Dans votre exemple cité, la solution la plus propre est:

val xs = List((1,2)->3,(4,5)->6,(7,8)->9)
xs map { case (a,b) => (a.swap, b) }
10
Kevin Wright
val b = a map { case ((x,y), u) => ((y,x), u) }
4
Daniel C. Sobral