Ich habe mir Folgendes angeschaut die Liste der Erhebungen, die am scala-lang.org und bemerkte eine merkwürdige Frage: " Können Sie alle Verwendungen von "_" nennen? ". Können Sie das? Wenn ja, tun Sie es bitte hier. Erläuternde Beispiele sind willkommen.
Antworten
Zu viele Anzeigen?Mir fallen folgende Beispiele ein
Existenzielle Typen
def foo(l: List[Option[_]]) = ...
Höherwertige Typparameter
case class A[K[_],T](a: K[T])
Ignorierte Variablen
val _ = 5
Ignorierte Parameter
List(1, 2, 3) foreach { _ => println("Hi") }
Ignorierte Namen von Selbsttypen
trait MySeq { _: Seq[_] => }
Wildcard-Muster
Some(5) match { case Some(_) => println("Yes") }
Platzhaltermuster in Interpolationen
"abc" match { case s"a$_c" => }
Sequenzplatzhalter in Mustern
C(1, 2, 3) match { case C(vs @ _*) => vs.foreach(f(_)) }
Wildcard-Einfuhren
import java.util._
Versteckte Einfuhren
import java.util.{ArrayList => _, _}
Verbindungsschreiben an die Betreiber
def bang_!(x: Int) = 5
Zuweisungsoperatoren
def foo_=(x: Int) { ... }
Platzhalter-Syntax
List(1, 2, 3) map (_ + 2)
Werte der Methode
List(1, 2, 3) foreach println _
Umwandlung von Call-by-Name-Parametern in Funktionen
def toFunction(callByName: => Int): () => Int = callByName _
Standard-Initialisierer
var x: String = _ // unloved syntax may be eliminated
Vielleicht gibt es noch andere, die ich vergessen habe!
Ein Beispiel zeigt, warum foo(_)
y foo _
sind unterschiedlich:
Dieses Beispiel kommt von 0__ :
trait PlaceholderExample {
def process[A](f: A => Unit)
val set: Set[_ => Unit]
set.foreach(process _) // Error
set.foreach(process(_)) // No Error
}
Im ersten Fall, process _
stellt eine Methode dar; Scala nimmt die polymorphe Methode und versucht, sie durch Ausfüllen des Typparameters monomorph zu machen, stellt aber fest, dass es keine Typ die ausgefüllt werden können für A
die den Typ (_ => Unit) => ?
(Existentiell _
kein Typ ist).
Im zweiten Fall, process(_)
ist ein Lambda; wenn man ein Lambda ohne expliziten Argumenttyp schreibt, leitet Scala den Typ aus dem Argument ab, das foreach
erwartet, und _ => Unit
est ein Typ (wohingegen nur einfache _
nicht), so dass es ersetzt und abgeleitet werden kann.
Dies ist vielleicht das kniffligste Problem in Scala, dem ich je begegnet bin.
Beachten Sie, dass dieses Beispiel in 2.13 kompiliert. Ignorieren Sie es, als ob es underscore zugewiesen wäre.
Von (meinem Eintrag) in der FAQ , für deren Vollständigkeit ich keine Garantie übernehme (ich habe erst vor zwei Tagen zwei Einträge hinzugefügt):
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
1_000_000 // Numeric literal separator (Scala 2.13+)
Dies ist auch Teil der diese Frage .
Eine ausgezeichnete Erklärung der Verwendung des Unterstrichs ist Scala _ [Unterstrich] magic .
例
def matchTest(x: Int): String = 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))
In Scala, _
wirkt ähnlich wie *
in Java beim Importieren von Paketen.
// 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 => _ , _ }
In Scala wird für alle nicht-privaten Variablen eines Objekts implizit ein Getter und Setter definiert. Der Getter-Name ist derselbe wie der Variablenname und _=
für den Namen des Setzers hinzugefügt.
class Test {
private var a = 0
def age = a
def age_=(n:Int) = {
require(n>0)
a = n
}
}
Verwendung:
val t = new Test
t.age = 5
println(t.age)
Wenn Sie versuchen, eine Funktion einer neuen Variablen zuzuweisen, wird die Funktion aufgerufen und das Ergebnis der Variablen zugewiesen. Diese Verwirrung entsteht durch die optionalen geschweiften Klammern beim Methodenaufruf. Wir sollten _ nach dem Funktionsnamen verwenden, um sie einer anderen Variablen zuzuweisen.
class Test {
def fun = {
// Some code
}
val funLike = fun _
}
Hier sind einige weitere Beispiele, bei denen _
verwendet wird:
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)
In allen obigen Beispielen steht ein Unterstrich für ein Element in der Liste (bei reduce steht der erste Unterstrich für den Akkumulator)
- See previous answers
- Weitere Antworten anzeigen