2016-05-08 6 views
0

Versuchen, meinen Kopf um die verschiedenen Verwendungen der _ zu wickeln. Im Moment habe ich mit diesem Beispiel bin zu kämpfen:Scala Verwendung von Unterstrich als Objekt Platzhalter

object Chapter9 extends App { 
    FileMatcher.filesEnding(".scala").foreach(println) 
} 

object FileMatcher { 
    private def filesHere = (new java.io.File(".")).listFiles 

    private def filesMatching(matcher: String => Boolean) = { 
    for (file <- filesHere; if matcher(file.getName)) 
    yield file 
    } 

    def filesEnding(query: String) = 
    filesMatching(_.endsWith(query)) 

    def filesContaining(query: String) = 
    filesMatching(_.contains(query)) 

    def filesRegex(query: String) = 
    filesMatching(_.matches(query)) 
} 

So klar wollen wir abstrahieren die gemeinsame Arbeit von looping/Filterung /, wobei für die unterschiedlichen Arten von Matcher, macht Sinn, es in einer Hilfsfunktion zu setzen.

Ich werde auf dem _.endsWith Teil aufgehängt. Nach meinem Verständnis wird dieser Unterstrich (der erste und einzige im Methodenkörper verwendete) durch den ersten Parameter ausgefüllt, der in diesem Fall query ist. Ich habe versucht, diese Theorie zu testen, indem ich Folgendes mache:

Aber das Programm druckt nichts. Was ist _ hier? Wie weiß Scala, welches Objekt nach einer endsWith Methode zu suchen ist?

Es sieht aus wie aus der Ausgabe des Programms, dass irgendwie file wird für diesen Unterstrich ausgefüllt, aber habe keine Ahnung, wie. Vielleicht bleibt der Unterstrich ein „Platzhalter“, bis es im Inneren filesMatching ‚s Körper verwendet wird und von diesem Punkt die nächste einschließende Umfang ist die for und der erste„Parameter is file`?

+0

http://stackoverflow.com/questions/8000903/what-are-all-the-uses-of-andunderscore-in-scala –

+0

http://stackoverflow.com/questions/1025181/hidden-features -of-scala/1083523 # 1083523 –

+0

Ich kann nicht sagen, ob nach unten abstimmen soll, weil die Frage nicht viel Sinn ergibt, oder ob es ein möglicher Punkt der Verwirrung für neue Benutzer ist. Es gibt viele von ihnen. –

Antwort

2

Blick auf die Unterschrift für filesMatching(). Beachten Sie, dass es dauert ein Argument vom Typ String => Boolean also ihr Argument eine Funktion, die sich ein String Argument nehmen und verwandelt es in eine Boolean

nun daran denken, dass eine anonyme Funktion sieht oft so etwas wie folgt aus:..

{ x => /* do something with x */ } 

Und in Fällen, in denen x nur einmal verwendet wird, kann dies zu einem einzigen _ abgekürzt werden. Also, rückwärts arbeiten, diese

filesMatching(_.endsWith(query)) 

neu geschrieben werden können, wie dies

filesMatching(x => x.endsWith(query)) 

so die filesMatching() Code sein Argument hat, eine Funktion, die eine Zeichenfolge (die in der anonymen Funktion nimmt ich x genannt habe). Diese Funktion, matcher, wird mit der Zeichenfolge file.getName aufgerufen, um eine zu erhalten. Der boolean Wert wird in einer if Klausel getestet:

if matcher(file.getName) 

TL; DR: Der Unterstrich ist eine Abkürzung für den file.getName String.

+0

Danke - aus irgendeinem Grund wurde ich auf den Unterstrich aufgelegt, von dem ich annahm, dass er versuchen würde, von 'filesEnding'" ausgefüllt "zu werden. Ich konnte die Punkte nicht mit dem ausführlicheren Funktionsliteral verbinden, das in Kurzschrift geschrieben wurde. Sehr geschätzt. – diplosaurus

0

Die kanonische Antwort ist What are all the uses of an underscore in Scala?

Aber -Xprint:parser zeigt

((x$1: String) => println((x$1: String))) 

, die mit Ausnahme des redundant getippt Ausdruck im Körper der Funktion uninteressant ist.

Es scheint keinen zusätzlichen Code zu generieren. Der Parameter ist bereits ein String.

Ich glaube nicht, dass Ihr Beispiel kompiliert? Oder ich weiß nicht, was du verlangst.

Explizite Typen können beim Debuggen helfen, wenn der Typ einer anonymen Funktion nicht wie gewünscht abgeleitet wird.

Edit: Ich gab diesen einen Versuch:

object Chapter9 extends App { 
    FileMatcher.filesEnding(".scala").foreach(println) 
} 

object FileMatcher { 
    private def filesHere = (new java.io.File(".")).listFiles 

    private def filesMatching(matcher: String => Boolean) = { 
    for (file <- filesHere; if matcher(file.getName)) 
    yield file 
    } 
def filesEnding(query: String) = { 
    println(_: String) 
} 
} 

Einen Ausdruck mit einem Unterstrich als eine anonyme Funktion seines erwarteten Typen muss ihm zu sagen, welche Art der Unterstrich ist, sofern nicht explizit kommentierte wie Sie. Aber das ist nicht üblich.

Statt (_: Int) * 2, (i: Int) => i * 2, aber das ist eine Stilfrage.

+1

IntelliJ beschwert sich über die 'FileMatcher' Vorwärtsreferenz, aber anders als das kompiliert es gut. – jwvh