Warum Compiler Scala nicht übersetzt
%Vor%zu Java entspricht
%Vor%Die Frage ist: Warum foldLeft und redudeLeft sind rekursiv, aber ihre richtigen Gegenstücke nicht?
Hier sind Links, die sagen, dass Rechtshänder nicht tail rekursiv sind. Ich frage, warum es so ist.
Woher weißt du, wann man fold-left und wann man fold-right benutzt?
(1, 2, 3, 4, 5, 6)
ist ein 6-wertiges Tupel, das nicht foldRight
, aber Array(1, 2, 3, 4, 5, 6)
hat.
ArrayLike
ist eine Merkmalunterklassierung von indexierten Sequenzen mit effizientem Elementzugriff, dh es wurden bestimmte Methoden optimiert, einschließlich zum Beispiel foldRight
. Jedes Array wird implizit in eine Unterklasse des Attributs ArrayLike
konvertiert. Von Scala Stamm:
Bytecode:
%Vor%EDIT: Die Methode in Bytecode ist iterativ, was bedeutet, dass der Compiler eine Tail-Call-Optimierung angewendet haben muss.
Ohne einen effizienten Elementzugriff (dh eine effiziente apply
-Methode) ist die beste generische Methode die Verwendung von Iteratoren und einer nicht-tail-rekursiven Funktion, um foldRight
zu implementieren, oder das Umkehren der Sammlung durch Erstellen einer neuen und Ausführen von a foldLeft
(letzteres ist zur Zeit getan). Bei allen Sequenzen mit effizientem Direktzugriff wird dieses Verhalten außer Kraft gesetzt und optimiert.
Es ist eine Frage, wie das Falten voranschreitet. Die Operation foldLeft
arrangiert
als
%Vor% (was 4 ist) während foldRight
arrangiert
als
%Vor%(was -8 ist).
Stellen Sie sich vor, Sie ziehen die Zahlen 1, 2 und 3 aus einer Tüte und machen die Rechnung auf Papier.
In dem Fall foldRight
musst du es so machen:
Im Fall foldLeft
können Sie dies folgendermaßen tun:
Aber Sie würden nicht, weil Sie es auch so machen können:
Unabhängig davon, wie viele Zahlen in der Tasche enthalten sind, muss nur ein Wert auf Papier geschrieben sein. Tail Call Elimination (TCE) bedeutet, dass Sie anstelle einer großen Struktur von rekursiven Aufrufen auf dem Stack einen akkumulierten Wert ablegen und ersetzen können, während Sie fortfahren. (Das heißt, die rekursiv ausgedrückte Berechnung wird im Wesentlichen iterativ durchgeführt.)
Wie andere bereits festgestellt haben, ermöglicht eine Random-Access-Struktur wie ArrayLike
, dass foldRight
in eine foldLeft
-Operation umgeordnet wird und somit für TCE infrage kommt. Die obige Beschreibung gilt für Fälle, in denen dies nicht möglich ist.
Tags und Links scala functional-programming