2009-09-06 10 views
19

Als ich anfing, Scala zu betrachten, gefiel mir das Aussehen von Nachforschungen. Sie schienen ein bisschen wie die foreach-Schleifen zu sein, die ich von Java 5 gewohnt war, aber mit funktionalen Einschränkungen und einer Menge süßer syntaktischer Nettigkeit.Scala's For-Comprehensions: Vitalfunktion oder syntaktischer Zucker?

Aber wie ich den Scala Stil aufgenommen habe, finde ich, dass jedes Mal, wenn ich eine for-comprension verwenden könnte ich verwende map, flatMap, filter, reduce und foreach statt. Die Absicht des Codes scheint mir auf diese Weise klarer zu sein, mit weniger möglichen versteckten Überraschungen, und sie sind normalerweise auch kürzerer Code.

Soweit ich weiß, werden For-Comprehensions immer in diese Methoden kompiliert, also frage ich mich: Für was sind sie eigentlich? Fehle ich eine funktionale Revalation (es wäre nicht das erste Mal)? Tun For-Comprehensions etwas, was die anderen Features nicht können oder zumindest viel unhandlicher sein könnten? Leuchten sie unter einem bestimmten Anwendungsfall? Ist es wirklich nur eine Frage des persönlichen Geschmacks?

+2

Dies ist fast ein Duplikat http://stackoverflow.com/questions/1052476/Können-jemand-erklären-Scala-Ertrag. Diese Frage fragte sich, was "Ausbeute" bedeutet, und dieser fragt sich, was sein Zweck ist. Die Antworten sind ungefähr gleich. –

Antwort

13

Bitte beziehen Sie sich auf this question. Die kurze Antwort lautet, dass For-Comprehensions lesbarer sein können. Insbesondere wenn Sie viele verschachtelte Generatoren haben, wird der tatsächliche Umfang dessen, was Sie tun, klarer, und Sie brauchen keine großen Einzüge.

10

For-Comprehensions sind syntaktischer Zucker, aber das bedeutet nicht, dass sie nicht lebenswichtig sind. Sie sind normalerweise prägnanter als ihre erweiterte Form, was schön ist, aber vielleicht helfen sie Programmierern aus imperativen Sprachen, funktionale Konstrukte zu verwenden.

Als ich mit Scala angefangen habe, habe ich viel für Nachforschungen verwendet, weil sie mir bekannt waren. Dann habe ich fast komplett aufgehört, weil ich das Gefühl hatte, dass die zugrunde liegenden Methoden expliziter und damit klarer sind. Jetzt bin ich wieder dabei, Nachforschungen anzustellen, weil ich denke, dass sie besser die Absicht von dem, was ich tue, zum Ausdruck bringen, als die Mittel, dies zu tun.

3

Sie haben Recht. Das Verständnis ist syntaktischer Zucker. Ich glaube, die zugrunde liegenden Methoden sind prägnanter und einfacher zu lesen, wenn man sich daran gewöhnt hat.

Vergleichen Sie die folgenden äquivalenten Aussagen:

1. for (i <- 1 to 100; if (i % 3 == 0)) yield Math.pow(i, 2) 
2. (1 to 100).filter(_ % 3 == 0).map(Math.pow(_, 2)) 

Meiner Meinung nach ist die Zugabe des Semikolons in # 1 lenkt ab von dem Sinne, dass dies ein einzelner Kettensatz ist. Es gibt auch ein Gefühl, dass ich ein var (ist es 1, oder ist es 99, oder etwas dazwischen?), Die von einem ansonsten funktionalen Stil ablenkt.

Option 2 ist offensichtlich eine Kette von Methodenaufrufen für Objekte. Jedes Glied in der Kette gibt eindeutig seine Verantwortung an. Es gibt keine Zwischenvariablen.

Vielleicht für Verständnis sind als ein Komfort für Entwickler Übergang von Java enthalten. Egal, was gewählt wird, ist eine Frage von Stil und Vorliebe.

+0

"Sobald Sie an sie gewöhnt sind" - genau. Sobald ich Monaden verstand, wechselte ich zu den zugrunde liegenden Methoden. Das Verständnis war vorher eine nützliche Verbindung. –

+1

Sie brauchen kein Semikolon in 1: 'für (i <- 1 bis 100 if (i% 3 == 0)) ergibt Math.pow (i, 2)'. Darüber hinaus können Sie Klammern durch geschweifte Klammern ersetzen, um Semikolonrückschlüsse zu aktivieren. – Blaisorblade

+0

Danke @Blaisorblade Ich frage mich, ob das Semikolon im Jahr 2009 benötigt wurde. – Synesso

11

Eine weitere große Verwendung von for-Verständnis ist für interne DSL. ScalaQL ist ein großartiges Beispiel dafür. Es kann machen diese

val underAge = for { 
    p <- Person 
    c <- Company 
    if p.company is c 
    if p.age < 14 
} yield p 

in diesem

SELECT p.* FROM people p JOIN companies c ON p.company_id = c.id WHERE p.age < 14 

und eine ganze Menge mehr.

+0

@Erik Es hat funktioniert, als ich es versuchte. Es ist ein Link zu einer PDF-Datei. Wenn Sie die Datei immer noch nicht herunterladen können, googlen Sie sie einfach: ScalaQL: Sprachintegrierte Datenbankabfragen für Scala von Daniel Spiewak und Tian Zhao –

+0

Downvoted: die eigentliche Frage ist, ob es einen Vorteil von for-comprassions über ihre Entschuldung gibt - und Sie können diesen Code auch in entzuckter Form schreiben. ScalaQuery ist ein besseres Beispiel, da es eine verfügbare Implementierung in Produktionsqualität bietet. Dieses Papier wirft einen Blick auf zu viele wichtige Details, die zu empfehlen sind. – Blaisorblade

5

In einigen Fällen, für die Verständlichkeit kann Absicht besser ausdrücken, wenn sie es tun, verwenden Sie sie.

Beachten Sie auch, dass mit für Comprehensions, erhalten Sie Muster passend kostenlos. Zum Beispiel über eine Karte Iterieren ist viel einfacher mit für das Verständnis:

for ((key, value) <- map) println (key + "-->" + value)

als mit foreach:

map foreach { case (key, value) => println (key + "-->" + value) }

Verwandte Themen