Liste der "magischen" Funktionen von Scala

72

Wo finde ich eine Liste der Scala „magischen“ Funktionen finden, wie apply, unapply, update, +=, usw.?

Mit magischen Funktionen meine ich Funktionen, die zum Beispiel von einem syntaktischen Zucker des Compilers verwendet werden

o.update(x,y) <=> o(x) = y

Ich habe nach einer Kombination von scala magicund Synonymen von gegoogelt functions, aber ich habe nichts gefunden.

Ich interessiere mich nicht für die Verwendung von magischen Funktionen in der Standardbibliothek, sondern für welche magischen Funktionen es gibt.

Elazar Leibovich
quelle

Antworten:

79

Soweit ich weiss:

Getters / Setter im Zusammenhang mit:

apply
update
identifier_=

Mustervergleich:

unapply
unapplySeq

Zum Verständnis:

map
flatMap
filter
withFilter
foreach

Präfixoperatoren:

unary_+
unary_-
unary_!
unary_~

Darüber hinaus ist, konvertiert implizierten von A nach B Scala auch A <op>= Bin A = A <op> B, wenn die früheren Betreiber nicht definiert ist, „op“ ist nicht alphanumerischen und <op>=nicht !=, ==, <=oder >=.

Und ich glaube nicht, dass es einen einzigen Ort gibt, an dem alle syntaktischen Zucker von Scala aufgelistet sind.

Daniel C. Sobral
quelle
3
Vielleicht möchten Sie das unary_ hinzufügen! usw. Betreiber, die in einem der anderen Beiträge aufgeführt wurden, da dies die umfassendste Antwort auf die Frage hier zu sein scheint :)
Calum
1
Was ist identifier_=? Das habe ich noch nie gesehen.
Stefan Endrullis
@ StefanEndrullis Versuchen Sie dies:object X { var _x = 0; def x_=(n: Int) { _x = n }; def x = _x }; X.x = 5; println(X.x)
Daniel C. Sobral
@ Daniel C. Sobral: Ah, OK, identifiersollte nur ein Platzhalter sein. Ich habs. Vielen Dank.
Stefan Endrullis
1
Es gibt auch equalsdas wird von==
Nikita
17

Neben updateund applygibt es auch eine Reihe von unären Operatoren, die (glaube ich) als magisch gelten:

  • unary_+
  • unary_-
  • unary_!
  • unary_~

Fügen Sie dazu die regulären Infix / Suffix-Operatoren hinzu (die fast alles sein können) und Sie haben das komplette Paket.

Sie sollten sich unbedingt die Scala-Sprachspezifikation ansehen. Es ist die einzige maßgebliche Quelle für dieses Zeug. Es ist nicht so schwer zu lesen (solange Sie mit kontextfreien Grammatiken vertraut sind) und sehr leicht zu durchsuchen. Das einzige, was nicht gut angegeben wird, ist die XML-Unterstützung.

Daniel Spiewak
quelle
12

Es tut mir leid, wenn Ihre Frage nicht genau beantwortet wird, aber mein bisheriger Lieblings-WTF-Moment ist @ als Zuweisungsoperator innerhalb der Musterübereinstimmung. Dank der weichen Kopie von "Programming in Scala" fand ich ziemlich schnell heraus, was es war.

Mit @ können wir jeden Teil eines Musters an eine Variable binden. Wenn die Musterübereinstimmung erfolgreich ist, erfasst die Variable den Wert des Untermusters. Hier ist das Beispiel aus der Programmierung in Scala (Abschnitt 15.2 - Variablenbindung):

expr match {
  case UnOp("abs", e @ UnOp("abs", _)) => e
  case _ =>
}

Wenn die gesamte Musterübereinstimmung erfolgreich ist, wird der Teil, der mit dem UnOp-Teil ("abs", _) übereinstimmt, als Variable e verfügbar gemacht.

Und hier ist , was Programming Scala dazu sagt.

Dieser Link funktioniert nicht mehr. Hier ist eine, die es tut.

Yardena
quelle
Können Sie uns mitteilen, was der @ -Operator tut?
Elazar Leibovich
4

Ich werde auch _*für den Mustervergleich eine beliebige Anzahl von Parametern wie hinzufügen

case x: A(_*)

Und Operatorassoziativitätsregel aus dem Odersky-Spoon-Venners-Buch:

Die Assoziativität eines Operators in Scala wird durch sein letztes Zeichen bestimmt. Wie unter <...> erwähnt, wird jede Methode, die mit einem ':' Zeichen endet, für ihren rechten Operanden aufgerufen und übergibt den linken Operanden. Methoden, die mit einem anderen Zeichen enden, sind umgekehrt. Sie werden auf ihrem linken Operanden aufgerufen und übergeben den rechten Operanden. Also ergibt a * b a. * (B), aber a ::: b ergibt b.:::(a).


Vielleicht sollten wir auch das syntaktische Desugaring von für Ausdrücke erwähnen , die hier zu finden sind


Und (natürlich!) Alternative Syntax für Paare

a -> b //converted to (a, b), where a and b are instances

(Wie richtig ausgeführt, handelt es sich bei diesem nur um eine implizite Konvertierung , die über eine Bibliothek durchgeführt wird. Daher ist er wahrscheinlich nicht zulässig, aber ich finde, er ist ein häufiges Rätsel für Neulinge.)


pagoda_5b
quelle
1
IIRC ->ist nur eine Bibliotheksfunktion.
Elazar Leibovich
4

Ich möchte hinzufügen, dass es auch ein "magisches" Merkmal gibt - scala.Dynamic:

Ein Markermerkmal, das dynamische Aufrufe ermöglicht. Instanzen xdieses Merkmals ermöglichen Methodenaufrufe x.meth(args)für beliebige Methodennamen methund Argumentlisten argssowie Feldzugriffe x.fieldfür beliebige Feldnamen field.

Wenn ein Anruf von Haus aus nicht unterstützt wird x(dh wenn die Typprüfung fehlschlägt), wird er gemäß den folgenden Regeln neu geschrieben:

foo.method("blah")      ~~> foo.applyDynamic("method")("blah")
foo.method(x = "blah")  ~~> foo.applyDynamicNamed("method")(("x", "blah"))
foo.method(x = 1, 2)    ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2))
foo.field           ~~> foo.selectDynamic("field")
foo.varia = 10      ~~> foo.updateDynamic("varia")(10)
foo.arr(10) = 13    ~~> foo.selectDynamic("arr").update(10, 13)
foo.arr(10)         ~~> foo.applyDynamic("arr")(10)

Ab Scala 2.10 ist das Definieren direkter oder indirekter Unterklassen dieses Merkmals nur möglich, wenn die Sprachfeature-Dynamik aktiviert ist.

Sie können also Dinge wie tun

import scala.language.dynamics

object Dyn extends Dynamic {
  def applyDynamic(name: String)(a1: Int, a2: String) {
    println("Invoked " + name + " on (" + a1 + "," + a2 + ")");
  }
}

Dyn.foo(3, "x");
Dyn.bar(3, "y");
Petr
quelle
3

Sie sind in der Scala-Sprachspezifikation definiert. Soweit ich weiß, gibt es nur drei "magische" Funktionen, wie Sie erwähnt haben.

Scalas Getter und Setter können sich auch auf Ihre "Magie" beziehen:

scala> class Magic {
 |     private var x :Int = _
 |     override def toString = "Magic(%d)".format(x)
 |     def member = x
 |     def member_=(m :Int){ x = m }
 | }

defined class Magic

scala> val m = new Magic

m: Magic = Magic(0)

scala> m.member

res14: Int = 0

scala> m.member = 100

scala> m

res15: Magic = Magic(100)

scala> m.member += 99

scala> m

res17: Magic = Magic(199)
Eastsun
quelle
Wenn Sie für mich einen Beweis für diese Behauptung finden könnten, würden Sie meine Frage beantworten ;-) Ich nahm an, dass dies in den Spezifikationen enthalten sein wird, aber es ist kein lustiger Job, sie darin zu finden.
Elazar Leibovich
2
Scala-Sprachspezifikation: 6.15 Zuweisungen ... Wenn x eine in einer Vorlage definierte parameterlose Funktion ist und dieselbe Vorlage eine Setterfunktion x_ = als Mitglied enthält, wird die Zuweisung x = e als Aufruf x _ = (e) von interpretiert diese Setterfunktion. Analog wird eine Zuordnung f .x = e zu einer parameterlosen Funktion x als Aufruf f .x _ = (e) interpretiert. Eine Zuweisung f (args) = e mit einer Funktionsanwendung links vom Operator "=" wird als f .update (args, e) interpretiert, dh als Aufruf einer durch f definierten Aktualisierungsfunktion.
Eastsun
Ich erwähne, Beweise dafür, dass es keine mehr gibt.
Elazar Leibovich