2016-07-26 4 views
2

Hier ist mein Code ...Scala Infixschreibweise

val strings: Enumerator[String] = Enumerator("1","2","3","4") 

//create am Enumeratee using the map method on Enumeratee 

val toInt: Enumeratee[String,Int] = Enumeratee.map[String]{ 
    (s: String) => s.toInt 
} 
val toSelf: Enumeratee[String,String] = Enumeratee.map[String]{ 
    (s: String) => s 
} 
List("Mary", "Paul") map (_.toUpperCase) filter (_.length > 5) 

val r1 = strings |>> (toSelf &>> (toInt &>> sum)) 
val r2 = strings |>> toSelf &>> (toInt &>> sum) 
val r3 = strings |>> toSelf &>> toInt &>> sum // does not compile 

val foo1 = strings &> toInt |>> sum 
val foo2 = strings &> (toInt |>> sum) // does not compile 
val foo3 = (strings &> toInt) |>> sum 

Die Symbole | >>, & >>. &> sind Methoden. Ich bin verwirrt darüber, wie der Compiler Klammern um sie herum platziert. In der Zeile:

List("Mary", "Paul") map (_.toUpperCase) filter (_.length > 5) 

Der Compiler die Klammer wie dies das Einfügen:

((List("Mary", "Paul") map (_.toUpperCase))) filter (_.length > 5) 

In Wirklichkeit es kompiliert:

List("Mary", "Paul").map(((x$3: String) => x$3.toUpperCase()))(List.canBuildFrom[String]).filter(((x$4: String) => x$4.length().>(5))) 

In dem nachfolgenden Beispiel:

strings |>> toSelf &>> (toInt &>> sum) 

Der Compiler ist Inserti ng die Klammer wie folgt aus:

strings |>> (toSelf &>> (toInt &>> sum)) 

In Wirklichkeit stellt es an:

strings.|>> (toSelf.&>> (toInt.&>>(sum))) 

Manchmal scheint es, wie der Compiler Klammer von rechts Einsetzen der Compiler nach links (zweites Beispiel) und andere Zeiten, es scheint, fügt Klammern von links nach rechts ein (erstes Beispiel). Manchmal, wie in

val r3 = strings |>> toSelf &>> toInt &>> sum 

erwarte ich, dass es Klammer wie

val r3 = strings |>> (toSelf &>> (toInt &>> sum)) 

einzusetzen und stattdessen erhalte ich einen Compiler-Fehler.

Kann jemand bitte die Regeln zur Klammereinfügung für whitespace-getrennte Methoden erklären?

Antwort

2

Betrieb in infix notation have a precedence sie definiert, wie in der Beschreibung erwähnt:

Der Vorrang eines Infixoperator von der Bedienungs ersten Zeichen bestimmt wird. Zeichen sind unten aufgeführt Reihenfolge der Vorrang, mit Zeichen in der gleichen Zeile bei der Steigerung der gleichen Vorrang haben:

(all letters) 
| 
^ 
& 
= ! 
< > 
: 
+ - 
*/% 
(all other special characters) 

Precedence und Assoziativität von Operatoren die Gruppierung von Teile eines Ausdrucks wie folgt bestimmen .

  • Wenn es mehr Infix Operationen in einem Ausdruck, dann Operatoren mit höherer Priorität bindet stärker als Betreiber mit niedrigerem Vorrang.

  • Wenn es in Folge Infix Operationen e0; op1; e1; op2… opn; en mit den Betreibern op1,…,opnop1,…,opn der gleichen Vorrang, dann werden alle diese Betreiber müssen die gleiche Assoziativität haben.Wenn alle Operatoren linksassoziativ sind, wird die Sequenz als (…(e0;op1;e1);op2…);opn;en interpretiert. Andernfalls, wenn alle Operatoren rechtsassoziativ sind, wird die Sequenz als e0;op1;(e1;op2;(…opn;en)…).

  • interpretiert. Postfixoperatoren haben immer eine niedrigere Priorität als Infixoperatoren. Z.B. e1; op1; e2; op2 ist immer gleichbedeutend mit (e1;op1;e2);op2

Gemäß der Spezifikation soll, Ihr zweiter Ausdruck sein:

strings.|>>((toSelf.&>>toInt).&>>(sum))) 

Da | eine geringere Priorität als &, zum letzten Mal aufgerufen wird, und dann &>> sind assoziativ, so dass sie von links nach rechts aufgerufen werden.

+0

Die Methode '& >>' hat eine höhere Priorität als '| >>', und '& >>' bleibt assoziativ, also wird 'strings | >> toSelf & >> toInt & >> sum' als' interpretiert Strings | >> ((toSelf & >> toInt) & >> sum) '. –

+1

@JohnReed Yup, das habe ich gemeint. Sieht so aus, als hätte ich die Klammern vermasselt. Fest. –