Ausgabe
Der folgende Code fügt der res
Liste ein Element hinzu. Meine Frage ist, wie scala .::
Symbole intern übersetzt?
Code-Auszug:
var res = List[(Int, Int)]()
res .::= (1, 2)
res .::= (3, 4)
res
Ausgang:
res56: Liste[(Int, Int)] = Liste((1,2),(3,4))
Lösung
In diesem Snippet passieren einige Dinge. Bevor wir darauf eingehen, lassen Sie uns über den Unterschied zwischen var
und sprechen val
. Nämlich, dass eine mit dem val
Schlüsselwort deklarierte Variable unveränderlich ist, dh ihr Wert kann nicht geändert werden:
scala> val x = 1
x: Int = 1
scala> x = 2
<console>:13: error: reassignment to val
x = 2
^
Andererseits wird var
das Schlüsselwort verwendet, um eine veränderliche Variable zu deklarieren, dh ihr Wert kann geändert werden:
scala> var y = "bar"
y: String = bar
scala> y = "foo"
y: String = foo
Was wäre, wenn wir einen neuen Wert von berechnen wollten, indem wir y
an seinen aktuellen Wert anhängen?
scala> y = y + "bar"
y: String = foobar
Sicher, das funktioniert, aber es stellt sich heraus, dass es dafür eine Abkürzung gibt:
scala> y += "bar"
scala> y
res10: String = foobar
Übrigens ist in Scala +
nur der Name einer Methode, also y + "bar"
dasselbe wie y.+("bar")
. Hässlich, aber gültig. Ebenso y.+=("bar")
ist auch ein gültiger Ersatz für y += "bar"
.
Großartig, merken wir uns das für später. Next ist, wie andere bereits betont haben, ::
nur eine Methode , um einer Liste Elemente voranzustellen (von Java aus kann sie als aufgerufen werden someList.$colon$colon(someElement)
). Wichtig ist, dass die ::
Methode eine neue Liste zurückgibt :
scala> var letters = List("b", "c")
letters: List[String] = List(b, c)
scala> letters.::("a")
res1: List[String] = List(a, b, c)
scala> letters
res2: List[String] = List(b, c)
Was wäre, wenn wir auf die Liste setzen wollten, letters
die den Buchstaben “a” enthält?
scala> letters = letters.::("a")
letters: List[String] = List(a, b, c)
Beachten Sie, dass dies dem vorherigen Beispiel mit Zeichenfolgen sehr ähnlich sieht. Funktioniert die Kurzschrift auch hier?
scala> letters ::= "a"
scala> letters
res6: List[String] = List(a, b, c)
Ja tut es. letters.::=("a")
funktioniert auch.
Lassen Sie uns nun das ursprüngliche Snippet aufschlüsseln:
Schritt 1
Erstellen Sie eine Variable mit dem Namen res
und weisen Sie ihr eine leere, unveränderliche Liste zu. Diese leere Liste soll Paare von ganzen Zahlen enthalten (Int, Int)
.
var res = List[(Int, Int)]()
Hier ist eine alternative Möglichkeit, dasselbe zu tun:
var res = List.empty[(Int, Int)]
(was meiner Meinung nach etwas einfacher zu lesen ist)
Schritt 2
(1, 2)
Stellen Sie der Liste ein neues Element voran und weisen Sie res
die resultierende Liste wieder der zu res
.
res .::= (1, 2)
Oder ohne Leerzeichen:
res.::=(1, 2)
Kommt mir bekannt vor? Wir hätten es auch so schreiben können:
res = res.::(1, 2)
Schritt 3
Folgen Sie (3, 4)
der Logik in Schritt 2
Schritt 4
Drucken Sie den aktuellen Wert von aus res
, der sein sollte:List((3,4), (1,2))
Randnotiz
Verwirrenderweise ist der Compiler nachsichtig genug, um uns zu erlauben, beim Aufrufen nur einen einzigen Satz Klammern anzugeben ::
, obwohl wir eigentlich zwei Sätze haben sollten: einen für den Methodenaufruf und einen anderen für die Angabe eines Paares von Ganzzahlen. Es gibt also noch eine andere gültige Art, dasselbe zu schreiben res.::=((1, 2))
.
Allgemeiner:
scala> def first(p:(Int, Int)):Int = p._1
first: (p: (Int, Int))Int
scala> first(6,7)
res0: Int = 6
scala> first((6,7))
res1: Int = 6
scala> first(6 -> 7) //lolz! another one using implicit conversion
res2: Int = 6
Die implizite Konvertierung ist allgegenwärtig, da sie in Predef definiert ist. ArrowAssoc
Geist = geblasen
Ich empfehle auch einen Blick auf Was sind alle Instanzen von syntaktischem Zucker in Scala?
Beantwortet von – Andrej
Antwort geprüft von – Jay B. (FixError Admin)