2010-02-05 9 views
27

Warum Scala nicht den Rückgabetyp der Methode zu schließen, wenn es eine explizite return Aussage in dem Verfahren verwendet wird?Typ-Inferenz auf Methode Rückgabetyp

Zum Beispiel, warum der folgende Code kompilieren?

object Main { 
    def who = 5 
    def main(args: Array[String]) = println(who) 
} 

Aber das Folgende nicht.

object Main { 
    def who = return 5 
    def main(args: Array[String]) = println(who) 
} 

Antwort

30

Der Rückgabetyp einer Methode ist entweder die Art der letzten Anweisung in dem Block, der er oder die Art der Expression, die sie in Abwesenheit eines Blocks definiert definiert.

Wenn Sie return innerhalb einer Methode verwenden, stellen Sie eine andere Erklärung, aus der das Verfahren zurückkehren. Das bedeutet, dass Scala den Typ return an dem Punkt, an dem er gefunden wird, nicht bestimmen kann. Stattdessen müssen Sie bis zum Ende der Methode fortfahren, dann alle Exit-Punkte kombinieren, um ihre Typen abzuleiten, und dann zu jedem dieser Exit-Punkte zurückkehren und deren Typen zuweisen.

Um dies zu tun, würde die Komplexität des Compilers erhöhen und verlangsamen, für den einzigen Vorteil, nicht Rückgabetyp bei der Verwendung return angeben müssen. In dem vorliegenden System kommt andererseits der Schlußfolgerungs-Rückgabetyp frei von der begrenzten Inferenz, die Scala bereits verwendet.

Also, am Ende, in der Balance zwischen Compiler Komplexität und den Gewinnen werden mußte, wurde dieser als die ehemaligen nicht wert sein.

+5

Hallo Daniel. Ich verstehe deine Erklärung nicht. Scala muss aufgrund von if/else-Anweisungen bereits mehrere Ausdrücke und Exit-Punkte in Funktionen kombinieren. Und die Scala-Sprache hat Tonnen von boshaft komplexen Dingen, die IMO die meisten Scala-Programmierer nicht sehr gut verstehen oder verwenden (z. B. Kovarianz/Kontravarianz, Strukturtypen usw.). Dies fügt dem Compiler eine Menge Komplexität hinzu; so "macht den Compiler komplexer" scheint eine schwache Antwort. –

+4

@UrbanVagabond Sie haben den Teil "Gewinne als Kopf" verpasst. Nur weil etwas komplex ist, bedeutet es nicht, dass es sich lohnt, mehr Komplexität hinzuzufügen. Jetzt muss Scala nicht mehrere Ausdrücke und Exit-Punkte in if/else-Anweisungen kombinieren, denn wenn/else ein Ausdruck ist, keine Anweisungen. Das mag wie Haare spalten scheinen, aber der Unterschied ist sehr real. –

-2

Ich bin mir nicht sicher warum. Vielleicht nur um die Verwendung der return Aussage zu entmutigen. :)

1

Vor diesem Hintergrund (2.8.Beta1):

object Main { 
    def who = return 5 
    def main(args: Array[String]) = println(who) 
} 
<console>:5: error: method who has return statement; needs result type 
     def who = return 5 

... es scheint nicht versehentliches.

11

Es würde die Komplexität des Compilers (und der Sprache) erhöhen. Es ist einfach irre, Typ-Inferenz auf so etwas zu machen. Wie bei allen ähnlichen Inferenztypen funktioniert alles besser, wenn Sie einen einzelnen Ausdruck haben. Gestreute Rücksendeanweisungen erzeugen effektiv eine Menge impliziter Verzweigungen, die zur Vereinheitlichung sehr klebrig werden. Es ist nicht besonders hart, nur klebrig. Zum Beispiel:

Was, frage ich Sie, schließt der Compiler hier? Wenn der Compiler Inferenz mit expliziten Return-Anweisungen ausführt, müsste es Any sein. Tatsächlich würden viele Methoden mit expliziten Return-Anweisungen Any zurückgeben, selbst wenn Sie nicht heimlich mit nicht-lokalen Returns kommen. Wie ich schon sagte, klebrig.

Und obendrein, ist dies nicht eine Sprache-Funktion, die gefördert werden soll. Explizite Returns tun nicht Code Klarheit zu verbessern, es sei denn es gibt nur eine explizite Rückgabe und das am Ende der Funktion. Der Grund ist ziemlich einfach zu sehen, wenn Sie Code-Pfade als gerichtetes Diagramm anzeigen. Wie ich bereits sagte, erzeugen gestreute Renditen eine Menge impliziter Verzweigungen, die seltsame Blätter in Ihrem Graphen erzeugen, sowie eine Menge zusätzlicher Pfade im Hauptteil. Es ist einfach irre. Kontrollfluss ist viel einfacher zu sehen, wenn Ihre Zweige alle explizit sind (Mustervergleich oder if Ausdrücke) und Ihr Code wird viel funktionaler sein, wenn Sie sich nicht auf seitenwirksame return-Anweisungen verlassen, um Werte zu erzeugen.

So, wie einige andere „entmutigt“ -Funktionen in Scala (z asInstanceOf statt as), machten die Designer der Sprache eine bewusste Wahl Dinge weniger angenehm zu machen. Dies kombiniert mit der Komplexität, die es in die Typinferenz einführt, und der praktischen Nutzlosigkeit der Ergebnisse in allen außer den am meisten konstruierten Szenarien. Es macht einfach keinen Sinn für Scalac, diese Art von Schlussfolgerung zu versuchen.

Moral der Geschichte: Lernen nicht Ihre Rendite zu zerstreuen! Das ist ein guter Rat in jeder Sprache, nicht nur in Scala.

+0

@ Daniel ... „entmutigt“ -Funktionen in Scala (zB asInstanceOf nicht als)“.... Habe ich etwas verpasst? Ich erinnere mich nicht' as' als Funktion in Scala (aber ich bin ziemlich neu in Scala ., so kann es mein Fehler sein) – Jus12

+0

@ Daniel, ich glaube, eine noch bessere Empfehlung mit 'return's zu vermeiden wäre (bezogen: http://stackoverflow.com/questions/3770989/purpose-of-return-statement -in-scala) – Jus12

+1

Es gibt keine 'as' Funktion in Scala. Es ist ein' as' Operator in C# aber, dass Funktionen wie die 'asInstanceOf' Methode in Scala. viele Menschen neu in die Sprache Frage, warum Scala Gussmechanismus ist * so * ausführlich, und die Antwort ist einfach seine Verwendung zu verhindern. –