wake-up-neo.com

Scalas "postfix ops"

Ich habe eine halbe Stunde gesucht und kann es immer noch nicht herausfinden.

In SIP: Modularizing Language Features gibt es eine Reihe von Funktionen, die eine explizite "Aktivierung" in Scala 2.10 (import language.feature). Darunter befindet sich postfixOps, auf das ich nirgendwo einen Verweis finden kann. Was genau erlaubt diese Funktion?

55
dmitry

Hiermit können Sie die Operatorsyntax in der Postfix-Position verwenden. Beispielsweise

List(1,2,3) tail

eher, als

List(1,2,3).tail

In diesem harmlosen Beispiel ist es kein Problem, aber es kann zu Mehrdeutigkeiten führen. Dies wird nicht kompilieren:

val appender:List[Int] => List[Int] = List(1,2,3) ::: //add ; here
List(3,4,5).foreach {println}

Und die Fehlermeldung ist nicht sehr hilfreich:

    value ::: is not a member of Unit

Es wird versucht, die Methode ::: Für das Ergebnis des Aufrufs foreach vom Typ Unit aufzurufen. Dies ist wahrscheinlich nicht das, was der Programmierer beabsichtigt hat. Um das richtige Ergebnis zu erhalten, müssen Sie nach der ersten Zeile ein Semikolon einfügen.

58
Kim Stebel

Die einfachste Antwort aller Zeiten:

Das Löschen von Punkten aus Methoden ohne Parameter ist VERALTET !

List(1,2,3) reverse //is bad style and will lead to unpredicted behaviour
List(1,2,3) map(_*2) reverse //bad too, because reverse can take first method call from the next line (details below)

OK, um Punkte in Methoden zu löschen, die einen Parameter von Funktion höherer Ordnung wie map, filter, count und safe verwenden! Auch rein funktional Methoden wie Zip.

List(1,2,3) map(_*2) filter(_>2)
(List(1,2,3) map(_*2)).reverse //safe and good
List(1,3,5) Zip List(2,4,6)

Lange Antwort WARUM

case class MyBool(x: Boolean) {
  def !!! = MyBool(!x) //postfix
  def or(other: MyBool): MyBool = if(x) other else this //infix
  def justMethod0() = this //method with empty parameters
  def justMethod2(a: MyBool, b: MyBool) = this //method with two or more
  override def toString = if(x) "true" else "false"
}

1) Postfix-Operator - ist eigentlich ein Methodenaufruf ohne Parameter (a! == a.!) Und ohne Klammern. (gilt als nicht sicher und veraltet)

val b1 = MyBool(false) !!!
List(1,2,3) head

2) Der Postfix-Operator ist eine Methode, die die Zeile beenden soll, andernfalls wird sie als Infix behandelt.

val b1 = MyBool(true) no! no! //ERROR
//is actually parsed like
val b2 = MyBool(true).no!(no!) //(no!) is unknown identifier
//as bad as
Vector(1,2,3) toList map(_*2) //ERROR

3) Der Infix-Operator ist eine Methode mit einem Parameter, die ohne Punkte und Klammern aufgerufen werden kann. Nur für rein funktionale Methoden

val c1 = MyBool(true) or b1 or MyBool(true)
val c2 = MyBool(true).or(b1).or(MyBool(true))
c1 == c2

4) Eine Methode mit einem oder mehreren Parametern wird ohne Punkt verkettet, wenn Sie sie mit Parametern aufrufen. def a (), def a (x), def a (x, y) Dies sollten Sie jedoch nur für Methoden tun, die Funktion höherer Ordnung als Parameter verwenden!

val d1 = MyBool(true) justMethod2(b1, c1) or b1 justMethod0() justMethod2(c1, b1)
//yes, it works, but it may be confusing idea
val d2 = MyBool(true).justMethod2(b1,c1).or(b1).justMethod0().justMethod2(c1, b1)
d1 == d2
//looks familiar? This is where it should be used:
List(1,2,3) filter(_>1) map(_*2)

Beispielwarnungen:

warnung: Es gab 1 Verwerfungswarnung (en). Wiederholen Sie die Ausführung mit -deprecation für Details. Warnung: Der Endpunkt des Postfix-Operators sollte aktiviert werden, indem der implizite Wert scala.language.postfixOps sichtbar gemacht wird. Dies kann durch Hinzufügen der Importklausel 'import scala.language.postfixOps' oder durch Festlegen der Compileroption -language: postfixOps erreicht werden. In den Scala Docs zum Wert scala.language.postfixOps finden Sie eine Erläuterung, warum die Funktion explizit aktiviert werden sollte.

30
Alex

Es bezieht sich auf die Fähigkeit, eine nulläre Methode (ohne Argumentliste oder leere Argumentliste) als Postfix-Operator aufzurufen:

Zum Beispiel:

case class MyBool(value: Boolean) {
    def negated = new MyBool(!value)
}
val b1 = MyBool( true )
val b2 = b1 negated // Same as b1.negated

Siehe: http://www.scala-lang.org/node/118

5