2012-05-03 3 views
6

Könnte jemand sagen was std.algorithm.map zurückgibt? (Link zu einem gewissen Dokumentationsseite wäre sehr geschätzt) Aus Fehlermeldung ist das Ergebnis vom Typ ResultErgebnis von std.algorithm.map

ulong[] x = [1,2,3]; 
ulong[] y = std.algorithm.map!"a"(x); // Error: cannot implicitly convert <..> of type Result to ulong[] 

In http://dlang.org/phobos/std_algorithm.html#map es recht wenig Informationen ist es:

The call map!(fun)(range) returns a range of which elements are obtained by applying fun(x) left to right for all x in range 

Daraus es nicht ist klar, was ich damit machen kann oder was nicht.

Antwort

7

Sie sollten nicht wissen oder interessieren, was std.algorithm.map zurück über die Tatsache hinausgeht, dass es eine Strecke des gleichen Genres wie das ist, das hereingebracht wird (vorwärts, bidirektional, zufällig, etc.). Bei den meisten bereichsbasierten Funktionen ist dies der Fall. Sie geben fast immer entweder einen neuen Bereich zurück, der den übergebenen Bereich umspannt, oder einen exakt gleichen Typ des Bereichs, der übergeben wurde (z. B. map tut der erstere; find tut letzteres). Verwenden Sie auto:

ulong[] x = [1, 2, 3]; 
auto y = map!"a"(x); 

Der Bereich zurück von map faul ist. Es macht nichts, bis Sie darüber iterieren (es ruft dann die gegebene Funktion auf jedem folgenden front des zugrunde liegenden Bereichs). Es ist effizienter (und ermöglicht unendliche Bereiche). Der genaue Rückgabetyp hängt vom Typ des Bereichs ab, den Sie übergeben haben, und ist lokal für map, sodass Sie keinen direkt erstellen können. Sie müssen entweder auto verwenden, um den Typ zu schließen oder typeof die Art zu erhalten:

typeof(map!"a"(x)) y = map!"a"(x); 

jedoch nur allgemein typeof verwenden, wenn Sie eine Variable benötigen, die Sie nicht direkt initialisieren. auto ist fast immer der Weg zu gehen.

Wenn Sie einen Array aus dem Ergebnis der map (oder aus einem anderen Bereich) erstellen müssen, dann verwenden std.array.array:

ulong[] y = array(map!"a"(x)); 

Wenn Sie nicht wissen viel über Bereiche, dann sollten Sie vielleicht gelesen this. Leider gibt es derzeit keinen Artikel auf dlang.org, in dem Bereiche erklärt werden, aber dieser Link ist für ein Kapitel in einem Buch, das eines der Mitglieder der D-Community auf Türkisch schrieb und ins Englische übersetzt hat, und es deckt Bereiche fair ab Gut.

EDIT:

Walter Bright vor kurzem einen Artikel speziell über Typen geschrieben, die lokal zu einer Funktion sind aber von der Funktion zurückgegeben, die auch Sie aufklären helfen können. Sie bekommen sogar einen coolen Namen: Voldemort Types in D.

+0

"Sie sollten nicht wissen oder interessieren". Bitte korrigieren Sie mich, wenn ich falsch liege, aber wenn ich nicht wissen/kümmern sollte, dann sollte mein Beispiel kompilieren – dnsmkl

+1

Ich meine, dass Sie nicht wissen oder kümmern sollten, dass alles, was Sie darüber wissen müssen, dass es eine Reihe von ist Das gleiche Genre wie dasjenige, das übergeben wurde. Der genaue Typ ist spezifisch für 'map' und nicht etwas, das du verwenden wirst. Sie verwenden einfach "auto", um den Typ abzuleiten und den Bereich mit der API zu verwenden, die Bereiche haben. Wenn Sie möchten, dass es sich tatsächlich um einen bestimmten Typ handelt, müssen Sie ihn in diesen Typ mit einer Funktion konvertieren, die einen Bereich akzeptiert und den gewünschten Typ generiert (z. B. std.array.array). –

+0

Es scheint unnatürlich, dass ich gezwungen bin, 'auto' zu verwenden, um das Ergebnis der Karte zu verwenden (auch wenn ich laizy eval. Und Zeug mag) Wie auch immer, danke für die Antwort und den Link – dnsmkl

3

Der Ergebnisbereich ist "faul", er stellt nicht das Endergebnis dar.

Es kann in ein Array eingeschaltet werden, wenn Sie std.array importieren und wickeln Sie es in etwa so:

ulong[] y = array(std.algorithm.map!"a"(x)); 

oder

ulong[] y = std.algorithm.map!"a"(x).array; 

, wenn Sie mit DMD 2.059 oder später

Das Kartenergebnis kann auch direkt mit foreach iteriert werden:

auto result = std.algorithm.map!"a"(x); 
foreach (element; result) 
    writeln(to!string(element)); 
+0

Warum 2.059 oder später? Das hat ewig funktioniert. –

+0

@ Jonathan Er bezieht sich auf die UFCS-Notation – fwend

+0

Ah, okay. Ich habe missverstanden und gedacht, dass sich die "dmd 2.059 oder später" auf den Teil danach bezieht. 'array' sollte eigentlich immer noch parens haben oder es wird nicht mit' -property' kompiliert (und '-property' soll schließlich zum normalen Verhalten werden, was die Parens hier erfordert, da' array' nicht ist Ein Besitz). –

1

Result ist ein Typ innerhalb map(), der nicht benannt werden kann, weil es ein Voldemort Type ist.

Die eigentliche source code in Phobos sieht ungefähr so ​​aus:

template map(fun...) if (fun.length >= 1) 
{ 
    auto map(Range)(Range r) if (isInputRange!(Unqual!Range)) 
    { 
     //... 
     struct Result 
     { 
      //... 
     } 
     return Result(r); 
    } 
} 

Wenn Sie sich den Quellcode ansehen, werden Sie feststellen, dass Result ist nichts anderes als ein Bereich: es verfügt über die üblichen popFront() und empty() Methoden und andere Methoden abhängig von der Art des Bereichs, der zurückgegeben werden muss. Wenn Sie Typinferenz verwenden,

auto r = map!("a*a")(data); 

r als Result eingegeben werden, aber man kann es nicht direkt instanziiert werden.