Nach den Scala-Kursen auf Coursera zeigte Martin Odersky einen Beispielcode, der lautet:
%Vor% Und er sagte, dass Range
in ein Vector
umgewandelt wird, weil sie dieselbe Schnittstelle haben ( IndexedSeq
) und das Ergebnis nicht als Range
dargestellt werden konnte.
(Es war in seinem Beispiel klarer, da er ein Paar erzeugt hat, das nicht als Range
darstellbar ist.)
Ich bin nicht sicher zu verstehen, weil ich denke, dass er vorher gesagt hat, dass der erste Generator in einem Ausdruck die Art des Elements bestimmen wird, das geliefert werden wird, und es scheint nicht immer wahr zu sein, zumindest für Range
.
Und ich bin nicht sicher zu verstehen, warum die Ausgabe Vector
ist, weil Vector
möglicherweise nicht die einzige andere Implementierung ist, die das oben berechnete Ergebnis darstellen kann.
Kann mir bitte jemand helfen, diesen Teil zu verstehen?
map
benötigt ein CanBuildFrom
als implizites Argument. Ihre Aufgabe besteht darin, eine neue Sammlung zu erstellen, die der bereits vorhandenen (und der Art des Inhalts) entspricht. Da Range
kein beliebiges Zeug enthalten kann - nicht einmal beliebige ganze Zahlen - gibt es kein CanBuildFrom
, das ein Range
erzeugt. Der spezifischste Supertyp von Range
mit einem CanBuildFrom
ist IndexedSeq
. Die Sammlung, die dadurch erstellt wird, ist Vector
.
Wie ich sicher bin, erklärt Martin auch, dass for
comprehensions verketteten Aufrufen der Methoden map
und flatMap
entsprechen (übersetzt werden) und foreach
, wenn Sie yield
nicht verwenden. .
Der Grund, warum es im Allgemeinen zu einem Wert des Typs des ersten Generators führt, ist, dass map
und flatMap
im Allgemeinen denselben Typ wie ihr Empfänger zurückgeben ( map
auf List
gibt List
zurück usw.).
Nun besteht das Problem mit Range
s darin, dass sie keine Dinge darstellen können, die keine regulären Folgen von ganzen Zahlen sind. Folglich ist der Rückgabetyp von map
und flatMap
als Definiert für Range
kann nicht Range
sein. Die nächstbeste Übereinstimmung ist Vector
, die prototypische Implementierung einer indexierten Sequenz.
(Wenn Sie sich den Quellcode oder sogar die Scala Doc-Seite ansehen, mit der ich verlinkt habe, werden Sie sehen, dass es etwas komplizierter ist, dass nur der Rückgabetyp, aber konzeptionell, der Grund dafür ist. Bearbeiten: ... und jetzt hat Rex Kerr gerade die CanBuildFrom
Bombe fallen gelassen.)
Vector
ist die Standardimplementierung für IndexedSeq
. % Co_de% kann nicht als map
dargestellt werden, da die Klasse Range
eine Reihe von Zahlen enthält, die durch einen Start-, Stopp- und Schrittwert dargestellt werden können (ähnlich wie Range
in Python). In den API-Dokumenten wird angegeben, dass es sich um einen Sonderfall von range
handelt.
Wir können sehen, dass IndexSeq
uns einen Container mit Werten (1, 4, 9, 16, 25) liefert. Wir können einen Anfang und einen Stopp bekommen, aber keinen konstanten Schrittwert.
Tags und Links scala scala-collections