Warum wird ein Bereich nach der Kartenoperation in einen Vektor umgewandelt?

8

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?

    
Sebastien Lorber 29.10.2012, 22:15
quelle

3 Antworten

9

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 .

    
Rex Kerr 29.10.2012, 22:26
quelle
2

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.)

    
Philippe 29.10.2012 22:25
quelle
1

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.

    
adelbertc 29.10.2012 22:23
quelle

Tags und Links