Ich habe eine Funktion, die funktioniert, aber spezialisierter ist, als ich es möchte, und es gibt einige Ineffizienzen, die ich gerne beheben würde.
Die funktionierende aber fehlerhafte Funktion:
%Vor%Die Gründe, warum ich diese Implementierung nicht mag, sind:
i64
ist hart codiert und ich möchte diese Funktion für u64
und möglicherweise andere Rückgabetypen flat_map
übergebene Sperrung kann in allen Fällen nicht von LLVM entfernt werden und der nächste, den ich zu meiner idealen Funktion bekommen konnte:
%Vor%Die Probleme, die ich sehe, sind:
str::split_whitespace
übergebene Argument ist ein String
und wird nicht zu einem str
gezwungen
str::split_whitespace
übergebene Argument lange genug lebt Result::unwrap
beschwert sich nicht, dass das Merkmal core::fmt::Debug
für den Typ <U as core::str::FromStr>::Err
nicht implementiert ist.
Ich denke, dass mit cleveren Lifetime-Notation und Trait-Anforderungen mindestens zwei davon behoben werden könnten, und wer weiß, vielleicht gibt es einen Weg, drei für drei zu gehen.
Beispielcode mit einigen vorgeschlagenen Korrekturen:
%Vor% Leider gibt es keine Möglichkeit, das zu tun, was Sie wollen, wenn Sie sowohl die Generizität als auch das Fehlen von Zuweisungen beibehalten. Der Grund dafür ist, dass Sie jemanden brauchen, der Ihre String-Daten besitzt, aber wenn flat_map(str::split_whitespace)
über einen Iterator von eigenen Strings ausgeführt wird, dann gibt es niemanden mehr, der diese strings behält, weil str::split_whitespace
nur die angefragte Zeichenfolge ausborgt . Wenn Sie jedoch die Eigentumsrechte in der Aufrufkette "pushen", können Sie nicht vollständig generisch sein und eigene Zeichenfolgen nach Wert akzeptieren.
Daher gibt es zwei Lösungen: den gesamten Iterator zu einem Vec<String>
vorzusammeln (oder die Elemente, die von split_whitespace()
zurückgegeben wurden, in eigene Strings umzuwandeln und sie wieder in Vec
zu sammeln), oder ein Iterator von Referenzen.
Hier ist die allgemeinste Version, die ich mir für die erste Lösung vorstellen konnte:
%Vor%(versuchen Sie es hier )
Es ist im Grunde das gleiche wie das erste, aber allgemeiner. Beachten Sie auch, dass Sie die Teile der Saite nach split_whitespace()
nicht zuschneiden müssen - das letztere wird sicherstellen, dass die Teile der Saite keine Leerzeichen an ihren Seiten haben. Into<String>
bound erlaubt es, sowohl &str
als auch String
iterators zu übergeben, und im letzteren Fall werden keine zusätzlichen Kopien erstellt.
Alternativ können Sie jede Zeile separat in eigene Strings aufteilen:
%Vor% Hier müssen wir nur eine &str
s von Iterator-Elementen erhalten, nicht String
s, also habe ich AsRef<str>
verwendet. Allerdings muss jede Zeile nicht nur in eine Sequenz von String
s konvertiert werden; Diese Sequenz muss aus genau dem gleichen Grund, der oben beschrieben wurde, in einem Vektor gesammelt werden - sonst würde niemand die ursprünglichen Werte vom Typ S
vor der Zerstörung behalten.
Aber es ist möglich, das .map(String::from).collect::<Vec<_>>()
zu vermeiden, wenn Sie bereit sind, etwas Generizität zu verlieren. Dies ist die zweite Lösung, die ich oben erwähnt habe. Wir können einen Iterator über Referenzen akzeptieren:
(Probieren Sie hier )
Grob gesagt, S
-Werte gehören nun jemand anderem und ihre Lebensdauer ist größer als der Bereich von iter_to_min()
. Sie müssen also weder jedes Teil in String
transformieren noch das gesamte Split-Ergebnis sammeln ein Code%. Sie können jedoch keine Vec<String>
an diese Funktion übergeben. Sie können Vec<String>
jedoch übergeben:
In all diesen Beispielen habe ich vec.iter()
in Iterator
geändert - das ist fast immer das, was Sie verwenden möchten, anstatt nur IntoIterator
. So können Sie beispielsweise Sammlungen direkt an solche Funktionen übergeben. Zweitens habe ich Iterator
condition hinzugefügt, was notwendig ist, damit U::Err: Debug
funktioniert. Und schließlich, um das Problem mit "String not coercing to & amp; str" zu beheben, können Sie immer explizite Closures und Methodensyntax verwenden, die diesen Zwang für Sie tun würden.
Tags und Links generics performance rust idioms