web-dev-qa-db-fra.com

Correspondance de modèle sur une liste en Scala

Je suis un peu confus en ce qui concerne la correspondance des modèles sur une liste de Scala.

Par exemple.

    val simplelist: List[Char] = List('a', 'b', 'c', 'd')

    //> simplelist  : List[Char] = List(a, b, c, d)

    def simple_fun(list: List[Char]) = list match {
           case (x:Char) :: (y:List[Char]) => println(x)
           case _ => Nil
     }                                                 
   //> simple_fun: (list: List[Char])Any

   simple_fun(simplelist)                            

   //> a
   //| res0: Any = ()

Ceci n’imprime actuellement qu’une seule ligne de sortie. Ne doit-il pas être exécuté/mis en correspondance sur chaque élément de la liste?

EDIT: J'ai corrigé les erreurs de compilation et copié la sortie du REPL.

10
Soumya Simanta

Sauf si vous appelez de manière répétée simple_fun d'une manière ou d'une autre, ce que vous avez là correspondra au motif du premier élément et rien de plus. Pour qu'il corresponde à toute la liste, vous pouvez obtenir que simple_fun s'appelle lui-même de manière récursive, comme ceci:

val simplelist: List[Char] = List('a', 'b', 'c', 'd')

def simple_fun(list: List[Char]): List[Nothing] = list match {
  case x :: xs => {
    println(x)
    simple_fun(xs)
  }
  case _ => Nil 
}

Remarque J'ai également omis certains types car le compilateur Scala peut les déduire, ce qui vous laisse un code moins encombré et plus lisible.

En petite remarque, appeler println à plusieurs reprises dans la fonction n'est pas particulièrement fonctionnel, car il s'agit d'effets secondaires. Une approche plus idiomatique consisterait à faire en sorte que la fonction construise une chaîne décrivant la liste, qui est ensuite affichée avec un seul appel à println - de sorte que les effets secondaires soient conservés dans un seul endroit bien défini. Quelque chose comme ceci serait une approche:

def simple_fun(list: List[Char]):String = list match {
  case x :: xs => x.toString + simple_fun(xs)
  case Nil => ""
}

println(simple_fun(simple_list))
23
Russell

Je pense que ce qui suit devrait fonctionner:

def flatten(l: List[_]): List[Any] = l match {
  case Nil => Nil
  case (head: List[_]) :: tail => flatten(head) ::: flatten(tail)
  case head :: tail => head :: flatten(tail)
}

La première ligne est un match pour Nil, donc si nous ne trouvons rien, rien ne retourne rien. La deuxième ligne identifie la liste de listes, rappelle la méthode d’aplatissement et aplatit la liste de listes.

0
Manoj Shah