Quelles sont toutes les utilisations d’un trait de soulignement dans Scala?

J’ai regardé la liste des sondages effectués sur scala-lang.org et j’ai remarqué une curieuse question: ” Pouvez-vous nommer toutes les utilisations de” _ “? “. Peut tu? Si oui, veuillez le faire ici. Des exemples explicatifs sont appréciés.

Ceux que je peux penser sont

Types existentiels

def foo(l: List[Option[_]]) = ... 

Paramètres de type supérieur

 case class A[K[_],T](a: K[T]) 

Variables ignorées

 val _ = 5 

Paramètres ignorés

 List(1, 2, 3) foreach { _ => println("Hi") } 

Noms ignorés des types de soi

 trait MySeq { _: Seq[_] => } 

Motifs génériques

 Some(5) match { case Some(_) => println("Yes") } 

Importations de caractères génériques

 import java.util._ 

Cacher les importations

 import java.util.{ArrayList => _, _} 

Joindre des lettres à la ponctuation

 def bang_!(x: Int) = 5 

Opérateurs d’affectation

 def foo_=(x: Int) { ... } 

Syntaxe de l’espace réservé

 List(1, 2, 3) map (_ + 2) 

Fonctions partiellement appliquées

 List(1, 2, 3) foreach println _ 

Conversion de parameters appel par nom en fonctions

 def toFunction(callByName: => Int): () => Int = callByName _ 

Il y en a peut-être d’autres que j’ai oubliés!


Exemple montrant pourquoi foo(_) et foo _ sont différents:

Cet exemple vient de 0__ :

 trait PlaceholderExample { def process[A](f: A => Unit) val set: Set[_ => Unit] set.foreach(process _) // Error set.foreach(process(_)) // No Error } 

Dans le premier cas, process _ représente une méthode; Scala prend la méthode polymorphe et tente de la rendre monomorphe en remplissant le paramètre type, mais réalise qu’il n’y a pas de type pouvant être rempli pour A qui donnera le type (_ => Unit) => ? (Existential _ n’est pas un type).

Dans le second cas, process(_) est un lambda; Lors de l’écriture d’un lambda sans argument explicite, Scala déduit le type de l’argument foreach par foreach , et _ => Unit est un type (alors que simplement _ not), il peut donc être substitué et déduit.

Cela pourrait bien être le piège le plus délicat de Scala que j’ai jamais rencontré.

De (mon entrée) dans la FAQ , que je ne garantis certainement pas d’être complète (j’ai ajouté deux entrées il y a seulement deux jours):

 import scala._ // Wild card -- all of Scala is imported import scala.{ Predef => _, _ } // Exception, everything except Predef def f[M[_]] // Higher kinded type parameter def f(m: M[_]) // Existential type _ + _ // Anonymous function placeholder parameter m _ // Eta expansion of method into method value m(_) // Partial function application _ => 5 // Discarded parameter case _ => // Wild card pattern -- matches anything val (a, _) = (1, 2) // same thing for (_ < - 1 to 10) // same thing f(xs: _*) // Sequence xs is passed as multiple parameters to f(ys: T*) case Seq(xs @ _*) // Identifier xs is bound to the whole matched sequence var i: Int = _ // Initialization to the default value def abc_<>! // An underscore must separate alphanumerics from symbols on identifiers t._2 // Part of a method name, such as tuple getters 

Cela fait également partie de cette question .

Scala _ [underscore] magic est une excellente explication des utilisations du trait de soulignement .

Exemples:

  def matchTest(x: Int): Ssortingng = x match { case 1 => "one" case 2 => "two" case _ => "anything other than one and two" } expr match { case List(1,_,_) => " a list with three element and the first element is 1" case List(_*) => " a list with zero or more elements " case Map[_,_] => " matches a map with any key type and any value type " case _ => } List(1,2,3,4,5).foreach(print(_)) // Doing the same without underscore: List(1,2,3,4,5).foreach( a => print(a)) 

Dans Scala, _ agit de manière similaire à * en Java lors de l’importation de packages.

 // Imports all the classes in the package matching import scala.util.matching._ // Imports all the members of the object Fun (static import in Java). import com.test.Fun._ // Imports all the members of the object Fun but renames Foo to Bar import com.test.Fun.{ Foo => Bar , _ } // Imports all the members except Foo. To exclude a member rename it to _ import com.test.Fun.{ Foo => _ , _ } 

Dans Scala, un getter et un setter seront implicitement définis pour tous les vars non privés dans un object. Le nom du getter est identique au nom de la variable et _= est ajouté pour le nom du setter.

 class Test { private var a = 0 def age = a def age_=(n:Int) = { require(n>0) a = n } } 

Usage:

 val t = new Test t.age = 5 println(t.age) 

Si vous essayez d’affecter une fonction à une nouvelle variable, la fonction sera appelée et le résultat sera affecté à la variable. Cette confusion se produit en raison des accolades facultatives pour l’invocation de la méthode. Nous devons utiliser _ après le nom de la fonction pour l’assigner à une autre variable.

 class Test { def fun = { // Some code } val funLike = fun _ } 

Il y a un usage que je peux voir tout le monde ici semble avoir oublié de lister …

Plutôt que de faire ça:

 List("foo", "bar", "baz").map(n => n.toUpperCase()) 

Vous pouvez simplement faire ceci:

 List("foo", "bar", "baz").map(_.toUpperCase()) 

Voici quelques exemples où _ est utilisé:

 val nums = List(1,2,3,4,5,6,7,8,9,10) nums filter (_ % 2 == 0) nums reduce (_ + _) nums.exists(_ > 5) nums.takeWhile(_ < 8) 

Dans tous les exemples ci-dessus, un trait de soulignement représente un élément de la liste (pour réduire, le premier trait de soulignement représente l'accumulateur)

Outre les usages que JAiro a mentionnés, j’aime bien celui-ci:

 def getConnectionProps = { ( Config.getHost, Config.getPort, Config.getSommElse, Config.getSommElsePartTwo ) } 

Si quelqu’un a besoin de toutes les propriétés de connexion, il peut faire:

 val ( host, port, sommEsle, someElsePartTwo ) = getConnectionProps 

Si vous avez besoin d’un hôte et d’un port, vous pouvez faire:

 val ( host, port, _, _ ) = getConnectionProps 
 import scala._ // Wild card -- all of Scala is imported import scala.{ Predef => _, _ } // Exclusion, everything except Predef def f[M[_]] // Higher kinded type parameter def f(m: M[_]) // Existential type _ + _ // Anonymous function placeholder parameter m _ // Eta expansion of method into method value m(_) // Partial function application _ => 5 // Discarded parameter case _ => // Wild card pattern -- matches anything f(xs: _*) // Sequence xs is passed as multiple parameters to f(ys: T*) case Seq(xs @ _*) // Identifier xs is bound to the whole matched sequence Please check the below link for more details https://docs.scala-lang.org/tutorials/FAQ/finding-symbols.html 

Il y a un exemple spécifique que “_” soit utilisé:

  type SsortingngMatcher = Ssortingng => (Ssortingng => Boolean) def starts: SsortingngMatcher = (prefix:Ssortingng) => _ startsWith prefix 

peut être égal à:

  def starts: SsortingngMatcher = (prefix:Ssortingng) => (s)=>s startsWith prefix 

L’application de «_» dans certains scénarios convertira automatiquement en «(x $ n) => x $ n»