Sie scheinen über die Antwort gestolpert zu sein. Wie auch immer, ich werde versuchen, es klar zu machen.
Sie können Punkte weglassen, wenn Sie die Präfix-, Infix- und Postfix-Notationen verwenden - die sogenannte Operator-Notation . Während Sie die Operator-Notation verwenden, können Sie die Klammer nur dann weglassen, wenn weniger als zwei Parameter an die Methode übergeben werden.
Jetzt ist die Operator-Notation eine Notation für den Methodenaufruf , was bedeutet, dass sie nicht verwendet werden kann, wenn das aufgerufene Objekt nicht vorhanden ist.
Ich werde kurz auf die Notationen eingehen.
Präfix:
Nur ~
, !
, +
und -
kann in Präfixnotation verwendet werden. Dies ist die Notation, die Sie beim Schreiben von !flag
oder verwenden val liability = -debt
.
Infix:
In dieser Notation wird die Methode zwischen einem Objekt und seinen Parametern angezeigt. Hier passen alle arithmetischen Operatoren.
Postfix (auch Suffix):
Diese Notation wird verwendet, wenn die Methode einem Objekt folgt und keine Parameter empfängt . Zum Beispiel können Sie schreiben list tail
, und das ist Postfix-Notation.
Sie können Infix-Notationsaufrufe problemlos verketten, solange keine Methode verwendet wird. Zum Beispiel möchte ich den folgenden Stil verwenden:
(list
filter (...)
map (...)
mkString ", "
)
Das ist das Gleiche wie:
list filter (...) map (...) mkString ", "
Warum verwende ich hier Klammern, wenn Filter und Map einen einzigen Parameter annehmen? Das liegt daran, dass ich ihnen anonyme Funktionen übergebe. Ich kann anonyme Funktionsdefinitionen nicht mit Infix-Stil mischen, da ich eine Grenze für das Ende meiner anonymen Funktion benötige. Die Parameterdefinition der anonymen Funktion kann auch als letzter Parameter der Infix-Methode interpretiert werden.
Sie können Infix mit mehreren Parametern verwenden:
string substring (start, end) map (_ toInt) mkString ("<", ", ", ">")
Curry-Funktionen sind mit der Infix-Notation schwer zu verwenden. Die Faltfunktionen sind ein klares Beispiel dafür:
(0 /: list) ((cnt, string) => cnt + string.size)
(list foldLeft 0) ((cnt, string) => cnt + string.size)
Sie müssen Klammern außerhalb des Infix-Aufrufs verwenden. Ich bin mir nicht sicher, welche genauen Regeln hier gelten.
Lassen Sie uns nun über Postfix sprechen. Postfix kann schwierig zu verwenden sein, da es nur am Ende eines Ausdrucks verwendet werden kann . Sie können beispielsweise Folgendes nicht tun:
list tail map (...)
Weil der Schwanz nicht am Ende des Ausdrucks erscheint. Das kannst du auch nicht:
list tail length
Sie können die Infixnotation verwenden, indem Sie das Ende der Ausdrücke in Klammern markieren:
(list tail) map (...)
(list tail) length
Beachten Sie, dass von der Postfix-Notation abgeraten wird, da sie möglicherweise unsicher ist .
Ich hoffe, das hat alle Zweifel ausgeräumt. Wenn nicht, schreibe einfach einen Kommentar und ich werde sehen, was ich tun kann, um ihn zu verbessern.
Klassendefinitionen:
val
odervar
kann in Klassenparametern weggelassen werden, wodurch der Parameter privat wird.Durch Hinzufügen von var oder val wird es öffentlich (dh es werden Methodenzugriffsmethoden und Mutatoren generiert).
{}
kann weggelassen werden, wenn die Klasse keinen Körper hat, d. h.Klasseninstanziierung:
Generische Parameter können weggelassen werden, wenn sie vom Compiler abgeleitet werden können. Beachten Sie jedoch, dass der Typparameter immer abgeleitet wird, wenn Ihre Typen nicht übereinstimmen. Ohne Angabe des Typs erhalten Sie möglicherweise nicht das, was Sie erwarten - das heißt, gegeben
Dies gibt Ihnen einen Typfehler (Int gefunden, erwartete Zeichenfolge)
Während dies gut funktioniert:
Weil der Typparameter T als der am wenigsten verbreitete Supertyp der beiden abgeleitet wird - Any.
Funktionsdefinitionen:
=
kann gelöscht werden, wenn die Funktion Unit (nichts) zurückgibt.{}
Denn der Funktionskörper kann gelöscht werden, wenn die Funktion eine einzelne Anweisung ist, aber nur, wenn die Anweisung einen Wert zurückgibt (Sie benötigen das=
Vorzeichen), d. h.aber das funktioniert nicht:
Der Rückgabetyp der Funktion kann weggelassen werden, wenn er abgeleitet werden kann (für eine rekursive Methode muss der Rückgabetyp angegeben werden).
()
kann gelöscht werden, wenn die Funktion keine Argumente akzeptiert, d. h.was konventionell Methoden vorbehalten ist, die keine Nebenwirkungen haben - dazu später mehr.
()
wird bei der Definition eines Pass-by-Name- Parameters nicht per se gelöscht , aber es handelt sich tatsächlich um eine ganz semantisch andere Notation, d. h.MyOp verwendet einen Parameter für die Namensübergabe, der im Gegensatz zu Funktionsparametern zu einem String führt (dh es kann sich um einen Codeblock handeln, der einen String zurückgibt).
Das heißt,
myOp
nimmt eine Funktion, die keine Parameter hat, und gibt einen String zurück.(Wohlgemerkt, Pass-by-Name-Parameter werden in Funktionen kompiliert; dies macht die Syntax nur schöner.)
()
kann in der Funktionsparameterdefinition gelöscht werden, wenn die Funktion nur ein Argument akzeptiert, zum Beispiel:Wenn jedoch mehr als ein Argument erforderlich ist, müssen Sie das () einschließen:
Aussagen:
.
kann gelöscht werden, um die Operator-Notation zu verwenden, die nur für Infix-Operatoren (Operatoren von Methoden, die Argumente annehmen) verwendet werden kann. Weitere Informationen finden Sie in Daniels Antwort ..
kann auch für die Liste der Postfix-Funktionen gelöscht werden()
kann für Postfix-Operatoren list.tail gelöscht werden()
kann nicht mit folgenden Methoden verwendet werden:Da diese Notation gemäß der Konvention für Methoden reserviert ist, die keine Nebenwirkungen haben, wie z. B. List # tail (dh der Aufruf einer Funktion ohne Nebenwirkungen bedeutet, dass die Funktion außer ihrem Rückgabewert keine beobachtbaren Auswirkungen hat).
()
kann für die Operatornotation gelöscht werden, wenn ein einzelnes Argument übergeben wird()
Möglicherweise müssen Postfix-Operatoren verwendet werden, die nicht am Ende einer Anweisung stehen()
Möglicherweise müssen verschachtelte Anweisungen, Enden anonymer Funktionen oder Operatoren angegeben werden, die mehr als einen Parameter verwendenWenn Sie eine Funktion aufrufen, die eine Funktion übernimmt, können Sie das () in der inneren Funktionsdefinition nicht weglassen, zum Beispiel:
Wenn Sie eine Funktion aufrufen, die einen By-Name-Parameter verwendet, können Sie das Argument nicht als parameterlose anonyme Funktion angeben. Zum Beispiel gegeben:
Sie müssen es nennen als:
oder
aber nicht:
IMO kann eine übermäßige Verwendung von Drop-Return-Typen schädlich für die Wiederverwendung von Code sein. Schauen Sie sich einfach die Spezifikation an, um ein gutes Beispiel für eine eingeschränkte Lesbarkeit zu finden, da der Code keine expliziten Informationen enthält. Die Anzahl der Indirektionsebenen, um tatsächlich herauszufinden, um welchen Typ es sich bei einer Variablen handelt, kann verrückt sein. Hoffentlich können bessere Tools dieses Problem abwenden und unseren Code präzise halten.
(OK, um eine vollständigere, präzisere Antwort zu erstellen (wenn ich etwas verpasst habe oder etwas falsch / ungenau gemacht habe, bitte kommentieren Sie), habe ich am Anfang der Antwort hinzugefügt. Bitte beachten Sie, dass dies keine Sprache ist Spezifikation, also versuche ich nicht, es genau akademisch korrekt zu machen - nur eher wie eine Referenzkarte.)
quelle
Eine Sammlung von Zitaten, die Einblick in die verschiedenen Bedingungen geben ...
Persönlich dachte ich, dass die Spezifikation mehr enthalten würde. Ich bin mir sicher, dass es das geben muss, ich suche einfach nicht nach den richtigen Worten ...
Es gibt jedoch einige Quellen, und ich habe sie zusammengestellt, aber nichts wirklich Vollständiges / Umfassendes / Verständliches / Das erklärt mir die oben genannten Probleme ...:
Ab Kapitel 2, "Weniger tippen, mehr tun", von Programmier-Scala :
Aus Kapitel 1, "Null bis Sechzig: Einführung in Scala", von Programming Scala :
Aus dem Blog-Beitrag Scala Syntax Primer :
Aus der Sprachspezifikation:
Von Scala für Java-Flüchtlinge Teil 6: Über Java hinwegkommen :
Welche Zeichen kann ich in Scala weglassen?
Was mich aber auch verwirrt, ist dieses Zitat:
Denn soweit ich sehen kann, gibt es ein Objekt, um den Anruf entgegenzunehmen ...
quelle
Ich finde es einfacher, dieser Faustregel zu folgen: In Ausdrücken wechseln Leerzeichen zwischen Methoden und Parametern. In Ihrem Beispiel wird
(service.findAllPresentations.get.first.votes.size) must be equalTo(2)
als analysiert(service.findAllPresentations.get.first.votes.size).must(be)(equalTo(2))
. Beachten Sie, dass die Klammern um die 2 eine höhere Assoziativität haben als die Leerzeichen. Punkte haben auch eine höhere Assoziativität,(service.findAllPresentations.get.first.votes.size) must be.equalTo(2)
würden also als analysieren(service.findAllPresentations.get.first.votes.size).must(be.equalTo(2))
.service findAllPresentations get first votes size must be equalTo 2
analysiert alsservice.findAllPresentations(get).first(votes).size(must).be(equalTo).2
.quelle
In der zweiten Lesung ist dies vielleicht der Schlüssel:
Wie im Blogbeitrag erwähnt: http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6 .
Vielleicht ist dies tatsächlich ein sehr strenger "Syntaxzucker", der nur funktioniert, wenn Sie effektiv eine Methode für ein Objekt aufrufen, das einen Parameter akzeptiert . z.B
Und sonst nichts.
Dies würde meine Beispiele in der Frage erklären.
Aber wie gesagt, wenn jemand darauf hinweisen könnte, wo genau in der Sprachspezifikation dies angegeben ist, wäre er sehr dankbar.
Ok, ein netter Kerl (paulp_ von #scala) hat darauf hingewiesen, wo in der Sprachspezifikation diese Informationen sind:
Hmm - für mich passt es nicht zu dem, was ich sehe oder ich verstehe es einfach nicht;)
quelle
Es gibt keine. Sie werden wahrscheinlich beraten, ob die Funktion Nebenwirkungen hat oder nicht. Das ist Schwindel. Die Korrektur besteht darin, keine Nebenwirkungen in dem von Scala zulässigen angemessenen Umfang zu verwenden. Soweit dies nicht möglich ist, sind alle Wetten ungültig. Alle Wetten. Die Verwendung von Klammern ist ein Element der Menge "all" und überflüssig. Sobald alle Wetten geschlossen sind, wird kein Wert mehr angezeigt.
Dieser Rat ist im Wesentlichen ein Versuch eines fehlgeschlagenen Effektsystems (nicht zu verwechseln mit: ist weniger nützlich als andere Effektsysteme).
Versuchen Sie, keine Nebenwirkungen zu verursachen. Akzeptieren Sie danach, dass alle Wetten geschlossen sind. Das Verstecken hinter einer de facto syntaktischen Notation für ein Effektsystem kann und tut nur Schaden anrichten.
quelle