web-dev-qa-db-fra.com

Pourquoi la correspondance de motifs dans Scala ne fonctionne-t-elle pas avec les variables?

Prenez la fonction suivante:

def fMatch(s: String) = {
    s match {
        case "a" => println("It was a")
        case _ => println("It was something else")
    }
}

Ce modèle correspond bien:

scala> fMatch("a")
It was a

scala> fMatch("b")
It was something else

Ce que j'aimerais pouvoir faire, c'est ce qui suit:

def mMatch(s: String) = {
    val target: String = "a"
    s match {
        case target => println("It was" + target)
        case _ => println("It was something else")
        }
}

Cela dégage l'erreur suivante:

fMatch: (s: String)Unit
<console>:12: error: unreachable code
               case _ => println("It was something else")

Je suppose que c'est parce qu'il pense que la cible est en fait un nom que vous souhaitez attribuer à ce que l'entrée est. Deux questions:

  1. Pourquoi ce comportement? La casse ne peut-elle pas simplement rechercher les variables existantes dans la portée qui ont le type approprié et les utiliser en premier et, si aucune n'est trouvée, traiter la cible comme un nom sur lequel filtrer les correspondances?

  2. Existe-t-il une solution à cela? Y a-t-il un moyen de faire correspondre les motifs aux variables? En fin de compte, on pourrait utiliser une grande instruction if, mais la casse de correspondance est plus élégante.

106
Henry Henrinson

Ce que vous recherchez est un identifiant stable. Dans Scala, ceux-ci doivent soit commencer par une lettre majuscule, soit être entourés de guillemets.

Les deux seraient des solutions à votre problème:

def mMatch(s: String) = {
    val target: String = "a"
    s match {
        case `target` => println("It was" + target)
        case _ => println("It was something else")
    }
}

def mMatch2(s: String) = {
    val Target: String = "a"
    s match {
        case Target => println("It was" + Target)
        case _ => println("It was something else")
    }
}

Pour éviter de se référer accidentellement à des variables qui existaient déjà dans la portée englobante, je pense qu'il est logique que le comportement par défaut soit que les modèles en minuscules soient des variables et non des identifiants stables. Ce n'est que lorsque vous voyez quelque chose commençant par des majuscules ou des tiques arrière, que vous devez être conscient qu'il provient de la portée environnante.

202
Ben James