2014-11-01 22 views
5

Ich versuche, für Comprehensions in Scala zu verstehen, und ich habe viele Beispiele, die ich irgendwie verstehen ...Scala für() vs für {}

Eine Sache, ich bin eine harte Zeit, Herauszufinden ist für() vs für {}. Ich habe beides ausprobiert, und es scheint, als könnte ich eine Sache in der einen machen, aber in der anderen bricht sie.

Zum Beispiel funktioniert das nicht:

def encode(number: String): Set[List[String]] = 
    if (number.isEmpty) Set(List()) 
    else { 
    for (
     split <- 1 to number.length 
     word <- wordsForNum(number take split) 
     rest <- encode(number drop split) 
    ) yield word :: rest 
    }.toSet 

jedoch, wenn Sie es {} ändern, tut es kompilieren:

def encode(number: String): Set[List[String]] = 
    if (number.isEmpty) Set(List()) 
    else { 
    for { 
     split <- 1 to number.length 
     word <- wordsForNum(number take split) 
     rest <- encode(number drop split) 
    } yield word :: rest 
    }.toSet         

Diese Beispiele aus einer Coursera Klasse ich bin nehmen. Der Professor erwähnte nicht das "Warum" in dem Video & Ich fragte mich, ob jemand anderes weiß.

Danke!

+0

Vielen Dank für die wirklich gründliche Antworten - ich nicht die Notwendigkeit für {} mit mehreren vs einzelne Zeile Beispiele verbinden habe ich arbeitete durch. – anonygrits

Antwort

7

Von der Syntax in der Spezifikation, könnte es scheinen, dass Pars und Klammern sind austauschbar:

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#for-comprehensions-and-for-loops

sondern weil die Generatoren von semis getrennt sind, die folgenden Regeln treten in :

http://www.scala-lang.org/files/archive/spec/2.11/01-lexical-syntax.html#newline-characters

ich habe gelesen und in der Vergangenheit diesen Abschnitt verstanden, aus dem ich den Kern vage erinnern, die Zeilenumbrüche in den geschweiften Klammern aktiviert sind, was zu sagen ist wird ein Zeilenumbruchzeichen als nl genommen, das als semi dient.

So können Sie die Generatoren auf separaten Zeilen anstelle von Semikolons setzen.

Dies ist die übliche "Semikolon-Inferenz", mit der Sie keine Semikola als Anweisungsabschlusszeichen schreiben können. So ist die Newline in der Mitte des Generators nicht als halb genommen, zum Beispiel:

scala> for (c <- 
    | List(1,2,3) 
    |) yield c+1 
res0: List[Int] = List(2, 3, 4) 

scala> for { c <- 
    | List(1,2,3) 
    | i = c+1 
    | } yield i 
res1: List[Int] = List(2, 3, 4) 
4

In Scala() sind in der Regel für, wenn Sie nur eine Aussage haben. So etwas hätte funktioniert:

def encode(number: String): Set[Int] = 
    if (number.isEmpty) Set() 
    else { 
    for (
     split <- 1 to number.length // Only one statement in the comprehension 
    ) split 
    }.toSet 

Fügen Sie einen weiteren hinzu und es würde nicht kompilieren. Das gleiche gilt für die Karte zum Beispiel

OK

List(1,2,3).map(number => 
    number.toString 
) 

Nicht OK (haben geschweiften Klammern verwenden)

List(1,2,3).map(number => 
    println("Hello world") 
    number.toString 
) 

Warum das so ist. Ich habe keine Ahnung :)

+0

Ich hatte vorher nicht bemerkt, dass die Mehrfachlinien {} erfordern. Netter Fang. – javadba

+1

@javadba Einige Leute (Odersky) setzen immer Klammern um mehrzeilige Ausdrücke, andere (paulp) bevorzugen Parens um einen einzelnen Ausdruck, der zufällig mehrzeilig ist. 'def f = (wenn (c) x sonst y)' –

+0

@ som-snytt thx für den Zeiger. Die Paren/Klammer ist verwirrend 2 mich. – javadba