2 Stimmen

Unterstrich in Funktionsliteralen weglassen?

scala> val alist = List(1,2,3,4,5)
alist: List[Int] = List(1, 2, 3, 4, 5)

scala> alist filter { 2.< }
res2: List[Int] = List(3, 4, 5)

scala> alist filter { 2 < }
res3: List[Int] = List(3, 4, 5)

scala> alist filter { > 3 }
<console>:1: error: ';' expected but integer literal found.
       alist filter { > 3 }

Warum sollte { 2.< } y {2 <} arbeiten? Ich denke, ich sollte zumindest schreiben { 2 < _ } oder?

Eine Methode, die keine Argumente erfordert, Sie können alternativ den Punkt weglassen und die postx-Operatorschreibweise verwenden:

scala> val s = "Hello, world!"
s: java.lang.String = Hello, world!
scala> s toLowerCase
res4: java.lang.String = hello, world!

Aber hier, < Methode ist nicht die Art von Methode, die keine Argumente benötigt, richtig?

Können Sie mir sagen, was diese Verwendung ist?

2voto

Frank Punkte 10276

Der Grund dafür ist, dass 2 ist ein Objekt, wenn Sie also schreiben 2.< o 2 < (die in Scala eigentlich dasselbe sind), dann rufen Sie eine Methode < auf das Objekt 2 .

Wenn Sie nur schreiben < o > wird der Compiler nach einer solchen Methode im lokalen Bereich suchen, aber keine finden. Ähnlich verhält es sich beim Schreiben von > 3 benötigt der Compiler eine Methode > verfügbar ist, was nicht der Fall ist.

Sie können dieses Verhalten auch direkt in der Konsole sehen:

scala> 3.<
<console>:8: error: ambiguous reference to overloaded definition,
both method < in class Double of type (x: Char)Boolean
and  method < in class Double of type (x: Short)Boolean
match expected type ?
               3.<
                 ^

Wie Sie sehen können, sind mehrere Implikate definiert, die sich 3 in ein Objekt einer Klasse, die eine < Methode. Sie funktioniert also prinzipiell, kann aber nicht für sich allein stehen. Es funktioniert jedoch, wenn Sie mehr Typinformationen wie in Ihrem Beispiel haben.

Im Gegensatz dazu steht Folgendes:

scala> <(3)
<console>:8: error: not found: value <
              <(3)
              ^

Hier können Sie sehen, wie der Compiler nach einem eigenständigen < irgendwo. Beachten Sie, dass in der Fehlermeldung von einem Wert die Rede ist, aber das bedeutet immer noch, dass es sich um eine Funktion handeln könnte, da der Wertetyp möglicherweise (Int, Int) => Boolean oder so ähnlich.

1voto

Daniel C. Sobral Punkte 290004

Was geschieht, ist eine Eta-Erweiterung (6.26.5):

Die Eta-Expansion konvertiert einen Ausdruck vom Typ Methode in einen äquivalenten Ausdruck vom Typ Funktion.

In diesem Fall, 2 < ist ein Methodentyp: (einer der) Methode < en Int . Allerdings, filter erwartet einen Funktionstyp. In einem solchen Fall führt Scala eine automatische Eta-Erweiterung durch.

Beachten Sie, dass, da der Typ, der von filter bekannt ist, kann sie korrekt ableiten, was 2 < Methode aufgerufen wird.

1voto

Julien Gaugaz Punkte 321

2.< verweist auf zur Methode < des Objekts 2 in der Erwägung, dass 2.<(_) gibt eine neue Funktion mit einem Argument. Letzteres ist eine Abkürzung für (wird erweitert zu) (x: Int) => 2 < x wobei der Typ Int wurde vom Scala-Compiler aus dem Typ der Elemente von alist .

> 3 bezieht sich in Ihrem Fall nicht auf eine Methode oder ein Objekt eines Objekts. > ist ein legaler Scala-Bezeichner (für eine Methode, Funktion oder ein Objekt), aber 3 ist kein gesetzlicher Bezeichner (er beginnt mit einer Ziffer). > a könnte ein Verweis auf ein Mitglied sein a des Objekts > ( >.a ). Beides ist in Ihrem Beispiel aber nicht der Fall. _ > 3 gibt jedoch eine neue Funktion mit einem Argument zurück, die man auch so schreiben könnte (x: Int) => x > 3 .

Dies ist im Wesentlichen dasselbe wie die Antwort von Daniel C. Sobral und der Kommentar von incrop zu Franks Antwort, aber weniger formal und mit mehr Beispielen. Ich hoffe, das hilft, ein Gefühl dafür zu bekommen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X