Warum benötigt Scala Funktionen, um einen expliziten Rückgabetyp zu haben?

11

Ich habe vor kurzem angefangen, in Scala Programmieren zu lernen, und es hat bisher Spaß gemacht. Ich mag die Fähigkeit, Funktionen innerhalb einer anderen Funktion zu deklarieren, was einfach intuitiv zu tun scheint.

Ein kleiner Ärger, den ich über Scala habe, ist die Tatsache, dass Scala in seinen Funktionen einen expliziten Rückgabetyp benötigt . Und ich habe das Gefühl, dass dies die Ausdruckskraft der Sprache behindert. Es ist auch nur schwierig, mit dieser Anforderung zu programmieren. Vielleicht liegt es daran, dass ich aus der Javascript- und Ruby-Komfortzone komme. Aber für eine Sprache wie Scala, die Tonnen von verbundenen Funktionen in einer Anwendung hat, kann ich mir nicht vorstellen, wie ich in meinem Kopf genau überlege, welchen Typ die bestimmte Funktion, die ich schreibe, mit Rekursionen nach Rekursionen zurückgeben soll.

Diese Anforderung der expliziten Rückgabetypdeklaration für Funktionen stört mich nicht für Sprachen wie Java und C ++. Rekursionen in Java und C ++ wurden, wenn sie auftraten, häufig mit maximal 2 bis 3 Funktionen behandelt. Niemals sind mehrere Funktionen wie Scala miteinander verkettet.

Ich frage mich also, ob es einen guten Grund gibt, warum Scala die Anforderung von Funktionen mit explizitem Rückgabetyp haben sollte.

Müllabfuhr
quelle
5
Das tut es nicht - und ich verstehe nicht, warum es ein Problem wäre, wenn es so wäre.
Keith Thompson
1
Ich dachte es wäre so. Gibt es Fälle in Scala, in denen der Rückgabetyp für eine Funktion tatsächlich nicht eindeutig ist?
Müllabfuhr

Antworten:

15

Scala erfordert nicht für alle Funktionen einen expliziten Rückgabetyp, sondern nur für rekursive. Der Grund dafür ist, dass der Typinferenzalgorithmus von Scala (etwas in der Nähe von) ein einfacher Scan von Anfang bis Ende ist, der nicht in der Lage ist, einen Lookahead durchzuführen.

Dies bedeutet, dass eine Funktion wie diese:

def fortuneCookieJoke(message: String) = message + " in bed."

benötigt keinen Rückgabetyp, da der Scala-Compiler klar erkennen kann, dass der Rückgabetyp sein muss, ohne logische Variablen zu verwenden oder etwas anderes als die Parameter der Methode zu betrachten String.

Auf der anderen Seite eine Funktion wie diese:

def mapInts(f: (Int) => Int, l: List[Int]) = l match {
  case Nil => Nil
  case x :: xs => f(x) :: mapInts(f, xs)
}

Dies führt zu einem Fehler bei der Kompilierung, da der Scala-Compiler ohne Verwendung von Lookahead- oder Logikvariablen nicht genau sehen kann, um welchen Typ es sich mapIntshandelt. Das Beste, was es sagen könnte, wenn es klug genug wäre, ist, dass der Rückgabetyp ein Supertyp von ist List[Nothing], da er Nilvon diesem Typ ist. Das gibt ihm nicht annähernd genug Informationen, um den Rückgabetyp von genau zu bestimmen mapInts.

Bitte beachten Sie, dass dies spezifisch für Scala ist und dass es andere statisch typisierte Sprachen gibt (die meisten der Miranda / Haskell / Clean-Familie, die meisten der ML-Familie und einige verstreute andere), die viel umfassendere und leistungsfähigere Typinferenzalgorithmen verwenden als Scala verwendet. Beachten Sie auch, dass dies nicht ganz Scalas Schuld ist. Die nominale Subtypisierung und die Inferenz des gesamten Modultyps stehen grundsätzlich im Widerspruch zueinander, und die Designer von Scala haben sich aus Gründen der Java-Kompatibilität für die erstere gegenüber der letzteren entschieden, während die "reineren" statisch typisierten funktionalen Sprachen hauptsächlich mit der entgegengesetzte Wahl im Auge.

Pthariens Flamme
quelle
4
Tatsächlich besteht das Problem nicht darin, einen umfassenderen Typinferenzalgorithmus zu finden. Es geht darum, einen umfassenderen Algorithmus für die Typinferenzierung zu finden und gleichzeitig die hohe Qualität der Fehlermeldungen im aktuellen Scala-Compiler beizubehalten.
Jörg W Mittag
1
Wäre die korrekte Rückgabe nicht case Niltatsächlich leer List[Int]()? In diesem Fall könnte ein ausreichend intelligenter Compiler dies herausfinden. Das ist alles, was Devil's Advocate spielt, nehme ich an.
KChaloux