Die Scala-Syntax enthält viele Symbole. Da solche Namen mit Suchmaschinen schwer zu finden sind, wäre eine umfassende Liste hilfreich.
Was sind alle Symbole in Scala und was macht jedes von ihnen?
Insbesondere würde Ich mag darüber wissen ->
, ||=
, ++=
, <=
, _._
, ::
, und :+=
.
Antworten:
Ich teile die Operatoren zum Zweck des Unterrichts in vier Kategorien ein :
Es ist also ein Glück, dass die meisten Kategorien in der Frage vertreten sind:
Die genaue Bedeutung der meisten dieser Methoden hängt von der Klasse ab, die sie definiert. Zum Beispiel bedeutet
<=
on "kleiner oder gleich" . Das erste werde ich als Beispiel unten geben. ist wahrscheinlich die Methode, für die definiert wurde (obwohl es sich um das gleichnamige Objekt handeln könnte ), und wahrscheinlich die Methode, die für verschiedene Klassen definiert wurde .Int
->
::
List
:+=
Buffer
Also, lasst uns sie sehen.
Schlüsselwörter / reservierte Symbole
Es gibt einige Symbole in Scala, die besonders sind. Zwei von ihnen werden als richtige Schlüsselwörter angesehen, während andere nur "reserviert" sind. Sie sind:
Diese sind alle Teil der Sprache und können als solche in jedem Text gefunden werden, der die Sprache richtig beschreibt, wie z. B. Scala Specification (PDF) selbst.
Der letzte, der Unterstrich, verdient eine besondere Beschreibung, weil er so weit verbreitet ist und so viele verschiedene Bedeutungen hat. Hier ist ein Beispiel:
Wahrscheinlich habe ich jedoch eine andere Bedeutung vergessen.
Automatisch importierte Methoden
Wenn Sie das gesuchte Symbol in der obigen Liste nicht gefunden haben, muss es eine Methode oder ein Teil davon sein. Oft wird jedoch ein Symbol angezeigt, und die Dokumentation für die Klasse enthält diese Methode nicht. In diesem Fall betrachten Sie entweder eine Zusammensetzung einer oder mehrerer Methoden mit etwas anderem, oder die Methode wurde in den Gültigkeitsbereich importiert oder ist über eine importierte implizite Konvertierung verfügbar.
Diese sind immer noch auf ScalaDoc zu finden : Sie müssen nur wissen, wo Sie sie suchen müssen. Andernfalls sehen Sie sich den Index an (derzeit auf 2.9.1 defekt, aber abends verfügbar).
Jeder Scala-Code verfügt über drei automatische Importe:
Die ersten beiden stellen nur Klassen und Singleton-Objekte zur Verfügung. Die dritte enthält alle impliziten Konvertierungen und importierten Methoden, da
Predef
es sich um ein Objekt selbst handelt.Wenn Sie
Predef
schnell hineinschauen, sehen Sie einige Symbole:Jedes andere Symbol wird durch eine implizite Konvertierung verfügbar gemacht . Schauen Sie sich einfach die mit
implicit
diesem Tag gekennzeichneten Methoden an , die als Parameter ein Objekt vom Typ erhalten, das die Methode empfängt. Zum Beispiel:Im obigen Fall
->
wird in der KlasseArrowAssoc
durch die Methode definiertany2ArrowAssoc
, die ein Objekt vom Typ übernimmtA
, wobeiA
ein unbegrenzter Typparameter für dieselbe Methode gilt.Gängige Methoden
Viele Symbole sind also einfach Methoden für eine Klasse. Zum Beispiel, wenn Sie dies tun
Sie finden die Methode
++
direkt in der ScalaDoc for List . Es gibt jedoch eine Konvention, die Sie bei der Suche nach Methoden beachten müssen. Methoden, die mit Doppelpunkt (:
) enden , werden rechts statt links gebunden. Mit anderen Worten, während der obige Methodenaufruf äquivalent ist zu:Wenn ich stattdessen
1 :: List(2, 3)
hätte, wäre das gleichbedeutend mit:Sie müssen sich also den Typ auf der rechten Seite ansehen, wenn Sie nach Methoden suchen, die mit einem Doppelpunkt enden. Betrachten Sie zum Beispiel:
Die erste Methode (
+:
) bindet nach rechts und befindet sich aufList
. Die zweite Methode (:+
) ist nur eine normale Methode und bindet nach links - wieder aufList
.Syntaktische Zucker / Zusammensetzung
Hier sind einige syntaktische Zucker, die eine Methode verbergen können:
Die letzte ist interessant, weil jede symbolische Methode auf diese Weise zu einer zuweisungsähnlichen Methode kombiniert werden kann.
Und natürlich gibt es verschiedene Kombinationen, die im Code erscheinen können:
quelle
val c = ex(2)
stattval ex(c) = 2
?val ex(c) = 2
.Ein (guter, IMO) Unterschied zwischen Scala und anderen Sprachen besteht darin, dass Sie Ihre Methoden mit fast jedem Zeichen benennen können.
Was Sie aufzählen, ist keine "Interpunktion", sondern einfache Methoden, und als solche variieren ihre Verhaltensweisen von Objekt zu Objekt (obwohl es einige Konventionen gibt).
Überprüfen Sie beispielsweise die Scaladoc-Dokumentation für List , und Sie werden einige der hier erwähnten Methoden sehen.
Einige Dinge zu beachten:
In den meisten Fällen wird die
A operator+equal B
KombinationA = A operator B
wie in den Beispielen||=
oder übersetzt++=
.Methoden, die mit enden,
:
sind richtig assoziativ, das heißt, dasA :: B
ist tatsächlich soB.::(A)
.Die meisten Antworten finden Sie in der Scala-Dokumentation. Eine Referenz hier zu behalten würde doppelte Anstrengungen bedeuten und schnell ins Hintertreffen geraten :)
quelle
Sie können diese zuerst nach bestimmten Kriterien gruppieren. In diesem Beitrag erkläre ich nur den Unterstrich und den Rechtspfeil.
_._
enthält einen Punkt. Ein Punkt in Scala zeigt immer einen Methodenaufruf an . Also links von dem Zeitraum, in dem Sie den Empfänger haben, und rechts davon die Nachricht (Methodenname). Jetzt_
ist ein besonderes Symbol in Scala. Es gibt mehrere Beiträge dazu, zum Beispiel dieser Blogeintrag alle Anwendungsfälle. Hier handelt es sich um eine anonyme Funktionsverknüpfung , dh um eine Verknüpfung für eine Funktion, die ein Argument verwendet und die Methode_
darauf aufruft . Jetzt_
ist keine gültige Methode, also haben Sie mit Sicherheit_._1
etwas Ähnliches gesehen, dh eine Methode_._1
für das Funktionsargument aufgerufen._1
bis_22
sind die Methoden von Tupeln , die ein bestimmtes Element eines Tupels extrahieren. Beispiel:Nehmen wir nun einen Anwendungsfall für die Funktionsanwendungsverknüpfung an. Gegeben eine Karte, die Ganzzahlen Zeichenfolgen zuordnet:
Wooop, es gibt bereits ein weiteres Auftreten einer seltsamen Interpunktion. Der Bindestrich und die Zeichen größer als, die einem Rechtspfeil ähneln , sind ein Operator, der a erzeugt
Tuple2
. Es gibt also auch keinen Unterschied im Ergebnis des Schreibens(1, "Eins")
oder1 -> "Eins"
nur, dass letzteres leichter zu lesen ist, insbesondere in einer Liste von Tupeln wie dem Kartenbeispiel. Das->
ist keine Magie, es ist, wie einige andere Operatoren, verfügbar, da Sie alle impliziten Konvertierungen im Objektscala.Predef
im Gültigkeitsbereich haben. Die Konvertierung, die hier stattfindet, istWo
ArrowAssoc
hat die->
Methode, die die erstelltTuple2
. Somit1 -> "Eins"
ist der Anruf aktuellPredef.any2ArrowAssoc(1).->("Eins")
. OK. Nun zurück zur ursprünglichen Frage mit dem Unterstrich:Der Unterstrich hier verkürzt den folgenden äquivalenten Code:
Beachten Sie, dass die
map
Methode einer Map das Tupel aus Schlüssel und Wert an das Funktionsargument übergibt. Da wir nur an den Werten (den Zeichenfolgen) interessiert sind, extrahieren wir sie mit der_2
Methode im Tupel.quelle
->
Methode zu verstehen , aber Ihr Satz "Es gibt also auch keinen Unterschied im Ergebnis des Schreibens(1, "Eins")
oder1 -> "Eins"
" hat mir geholfen, die Syntax und ihre Verwendung zu verstehen.Als Ergänzung zu den brillanten Antworten von Daniel und 0__ muss ich sagen, dass Scala Unicode- Analoga für einige der Symbole versteht, also statt
man darf schreiben
quelle
In Bezug darauf
::
gibt es einen weiteren Stackoverflow- Eintrag, der den::
Fall abdeckt . Kurz gesagt, es wird verwendet, umLists
durch ' consing ' zu konstruieren und eine " werden. Es ist sowohl eine Klasse, die eine konsistente Liste darstellt als auch als Extraktor verwendet werden kann, aber am häufigsten ist es eine Methode in einer Liste. Als Pablo Fernandez weist darauf hin, da es in einem Doppelpunkt endet, ist es richtig assoziativ , den Empfänger der Methodenaufruf Sinn ist auf der rechten Seite , und das Argument für den der Betreiber überlassen. Auf diese Weise können Sie die Nachteile elegant ausdrücken, indem Sie einer vorhandenen Liste ein neues Kopfelement voranstellen :Dies entspricht
Die Verwendung als Extraktionsobjekt ist wie folgt:
Dies sieht hier wie ein Operator aus, ist aber wirklich nur eine andere (besser lesbare) Schreibweise
Weitere Informationen zu Extraktoren finden Sie in diesem Beitrag .
quelle
<=
ist genau so, als würden Sie es "lesen": "kleiner als oder gleich". Es ist also ein mathematischer Operator in der Liste von<
(ist kleiner als?),>
(Ist größer als?),==
(Ist gleich?),!=
(Ist nicht gleich?),<=
(Ist kleiner als oder gleich?) Und>=
(ist größer als ?) oder gleich?).Dies darf nicht mit einem doppelten Pfeil nach rechts verwechselt werden , der verwendet wird, um die Argumentliste vom Hauptteil einer Funktion zu trennen und um die Testbedingung beim Mustervergleich (einen Block) vom Hauptteil zu trennen, der ausgeführt wird, wenn eine Übereinstimmung auftritt . Sie können ein Beispiel dafür in meinen beiden vorherigen Antworten sehen. Erstens verwendet die Funktion:
=>
case
Dies wird bereits abgekürzt, da die Typen weggelassen werden. Die folgende Funktion wäre
und die Verwendung des Mustervergleichs:
quelle
Ich halte eine moderne IDE für entscheidend für das Verständnis großer Scala-Projekte. Da diese Operatoren auch Methoden sind, klicke ich in der Idee einfach mit gedrückter Ctrl-Taste oder Strg-B in die Definitionen.
Sie können bei gedrückter Ctrl-Taste nach rechts in einen Cons-Operator (: :) klicken und am Scala Javadoc landen und sagen: "Fügt ein Element am Anfang dieser Liste hinzu." Bei benutzerdefinierten Operatoren wird dies noch kritischer, da sie in schwer zu findenden Implikaten definiert werden können. Ihre IDE weiß, wo das Implizit definiert wurde.
quelle
Nur zu den anderen ausgezeichneten Antworten hinzufügen. Scala bietet zwei häufig kritisierte symbolische Operatoren an,
/:
(foldLeft
) und:\
(foldRight
) Operatoren, von denen der erste rechtsassoziativ ist. Die folgenden drei Aussagen sind also gleichbedeutend:Wie sind diese drei:
quelle
Scala erbt die meisten Rechenoperatoren von Java . Dies umfasst bitweises oder
|
(Einzelpipe-Zeichen), bitweises und&
bitweises Exklusiv-oder^
sowie logisches (Boolesches) oder||
(zwei Pipe-Zeichen) und logisches und&&
. Interessanterweise können Sie die Einzelzeichenoperatoren verwendenboolean
, sodass die logischen Java-Operatoren völlig redundant sind:Wie in einem anderen Beitrag erwähnt, werden Anrufe, die mit einem Gleichheitszeichen enden
=
, durch eine Neuzuweisung aufgelöst (wenn eine Methode mit diesem Namen nicht existiert!):Diese 'doppelte Überprüfung' ermöglicht es, eine veränderbare Sammlung leicht gegen eine unveränderliche Sammlung auszutauschen:
quelle
true | { println( "Icke" ); true }
⇒ druckt!true || { println( "Icke" ); true }
⇒ druckt nicht !