Ich möchte ein Modul mit mehreren Strukturen haben, jede in einer eigenen Datei. Am Beispiel eines Math
Moduls:
Math/
Vector.rs
Matrix.rs
Complex.rs
Ich möchte, dass sich jede Struktur in demselben Modul befindet, das ich aus meiner Hauptdatei verwenden würde, wie folgt:
use Math::Vector;
fn main() {
// ...
}
Das Modulsystem von Rust (das anfangs etwas verwirrend ist) bietet jedoch keine offensichtliche Möglichkeit, dies zu tun. Es scheint nur möglich zu sein, Ihr gesamtes Modul in einer Datei zu haben. Ist das nicht rustikal? Wenn nicht, wie mache ich das?
foo::bar::Baz
sollte struct infoo/bar.rs
oder definiert werdenfoo/bar/mod.rs
.Antworten:
Das Modulsystem von Rust ist tatsächlich unglaublich flexibel und ermöglicht es Ihnen, jede gewünschte Struktur verfügbar zu machen, während Sie verbergen, wie Ihr Code in Dateien strukturiert ist.
Ich denke, der Schlüssel hier ist die Verwendung
pub use
, mit der Sie Bezeichner aus anderen Modulen erneut exportieren können. Es gibt einen Präzedenzfall dafür in Rustsstd::io
Kiste, in der einige Typen aus Untermodulen zur Verwendung in erneut exportiert werdenstd::io
.Um Ihr Beispiel anzupassen, könnten wir mit dieser Verzeichnisstruktur beginnen:
Hier ist dein
main.rs
:Und dein
src/lib.rs
:Und schließlich
src/vector.rs
:Und hier geschieht die Magie. Wir haben ein Untermodul definiert
math::vector::vector_a
, in dem eine spezielle Art von Vektor implementiert ist. Wir möchten jedoch nicht, dass Kunden Ihrer Bibliothek sich darum kümmern, dass es einvector_a
Untermodul gibt . Stattdessen möchten wir es immath::vector
Modul verfügbar machen . Dies geschieht mitpub use self::vector_a::VectorA
, wodurch dievector_a::VectorA
Kennung im aktuellen Modul erneut exportiert wird.Sie haben jedoch gefragt, wie dies zu tun ist, damit Sie Ihre speziellen Vektorimplementierungen in verschiedenen Dateien ablegen können. Das macht die
mod vector_b;
Leitung. Es weist den Rust-Compiler an, nach einervector_b.rs
Datei für die Implementierung dieses Moduls zu suchen . Und natürlich ist hier unseresrc/vector_b.rs
Akte:Aus Sicht des Kunden ist die Tatsache, dass
VectorA
undVectorB
in zwei verschiedenen Modulen in zwei verschiedenen Dateien definiert sind, völlig undurchsichtig.Wenn Sie sich im selben Verzeichnis wie befinden
main.rs
, sollten Sie es ausführen können mit:Im Allgemeinen ist das Kapitel "Kisten und Module" im Rust-Buch ziemlich gut. Es gibt viele Beispiele.
Schließlich sucht der Rust-Compiler auch automatisch in Unterverzeichnissen nach Ihnen. Der obige Code funktioniert beispielsweise unverändert mit dieser Verzeichnisstruktur:
Die Befehle zum Kompilieren und Ausführen bleiben ebenfalls gleich.
quelle
math::Vec2
anstelle von zu verwendenmath::vector::Vec2
. (dh das gleiche Konzept, aber ein Modul tiefer.)Die Regeln für das Rust-Modul lauten:
Die Datei matrix.rs 1 im Verzeichnis math ist nur das Modul
math::matrix
. Es ist einfach. Was Sie in Ihrem Dateisystem sehen, finden Sie auch in Ihrem Quellcode. Dies ist eine Eins-zu-Eins-Entsprechung von Dateipfaden und Modulpfaden 2 .Sie können also eine Struktur
Matrix
mit importierenuse math::matrix::Matrix
, da sich die Struktur in der Datei matrix.rs in einem Verzeichnis math befindet. Nicht glücklich? Sie würdenuse math::Matrix;
stattdessen sehr viel bevorzugen , nicht wahr? Es ist möglich. Exportieren Sie den Bezeichnermath::matrix::Matrix
in math / mod.rs erneut mit:Es gibt noch einen weiteren Schritt, um dies zum Laufen zu bringen. Rust benötigt eine Moduldeklaration, um das Modul zu laden . Fügen Sie ein
mod math;
in main.rs. Wenn Sie dies nicht tun, erhalten Sie beim Importieren eine Fehlermeldung vom Compiler:Der Hinweis ist hier irreführend. Es sind keine zusätzlichen Kisten erforderlich, außer natürlich, dass Sie wirklich beabsichtigen, eine separate Bibliothek zu schreiben.
Fügen Sie dies oben in main.rs hinzu:
Die Moduldeklaration ist auch notwendig für die Submodule
vector
,matrix
undcomplex
, weilmath
Bedürfnisse sie laden sie erneut zu exportieren. Ein Reexport eines Bezeichners funktioniert nur, wenn Sie das Modul des Bezeichners geladen haben. Dies bedeutet, dassmath::matrix::Matrix
Sie den zu schreibenden Bezeichner erneut exportieren müssenmod matrix;
. Sie können dies in math / mod.rs tun. Erstellen Sie daher die Datei mit folgendem Inhalt:Aaaund du bist fertig.
1 Quelldateinamen beginnen normalerweise mit einem Kleinbuchstaben in Rust. Deshalb benutze ich matrix.rs und nicht Matrix.rs.
2 Java ist anders. Sie deklarieren den Pfad auch mit
package
. Es ist überflüssig. Der Pfad ist bereits aus dem Speicherort der Quelldatei im Dateisystem ersichtlich. Warum sollten Sie diese Informationen in einer Erklärung oben in der Datei wiederholen? Natürlich ist es manchmal einfacher, einen kurzen Blick auf den Quellcode zu werfen, als den Dateisystemspeicherort der Datei herauszufinden. Ich kann Leute verstehen, die sagen, dass es weniger verwirrend ist.quelle
Rusts Puristen werden mich wahrscheinlich als Ketzer bezeichnen und diese Lösung hassen, aber das ist viel einfacher: Machen Sie einfach alles in einer eigenen Datei und verwenden Sie dann das Makro " include! " In mod.rs:
Auf diese Weise erhalten Sie keine zusätzlichen verschachtelten Module und vermeiden komplizierte Export- und Umschreibregeln. Einfach, effektiv, ohne viel Aufhebens.
quelle
use super::*
). Sie können Code nicht vor anderen Dateien verbergen (was für die unsichere Verwendung sicherer Abstraktionen wichtig ist)Okay, ich habe eine Weile gegen meinen Compiler gekämpft und ihn endlich zum Laufen gebracht (danke an BurntSushi für den Hinweis
pub use
.main.rs:
math / mod.rs:
math / vector.rs
Andere Strukturen könnten auf die gleiche Weise hinzugefügt werden. HINWEIS: Kompiliert mit 0.9, nicht mit Master.
quelle
mod math;
inmain.rs
Paaren Ihrmain
Programm mit Ihrer Bibliothek. Wenn Sie möchten, dass Ihrmath
Modul unabhängig ist, müssen Sie es separat kompilieren und mit verknüpfenextern crate math
(wie in meiner Antwort gezeigt). In Rust 0.9 ist es möglich, dassextern mod math
stattdessen die Syntax lautet .Ich möchte hier hinzufügen, wie Sie Rust-Dateien einschließen, wenn sie tief verschachtelt sind. Ich habe folgende Struktur:
Wie greifen Sie darauf zu
sink.rs
odertoilet.rs
von ?main.rs
?Wie andere bereits erwähnt haben, kennt Rust keine Dateien. Stattdessen sieht es alles als Module und Submodule. Um auf die Dateien im Badezimmerverzeichnis zuzugreifen, müssen Sie sie exportieren oder nach oben verschieben. Dazu geben Sie einen Dateinamen mit dem Verzeichnis an, auf das Sie zugreifen möchten, und
pub mod filename_inside_the_dir_without_rs_ext
in der Datei.Beispiel.
Erstellen Sie eine Datei mit dem Namen
bathroom.rs
imhome
Verzeichnis:Exportieren Sie die Dateinamen:
Erstellen Sie eine Datei mit dem Namen
home.rs
nebenmain.rs
pub mod
die Datei bath.rsInnerhalb
main.rs
use
Anweisungen können auch verwendet werden:Einbindung anderer Geschwistermodule (Dateien) in Submodule
Wenn Sie
sink.rs
from verwendentoilet.rs
möchten, können Sie das Modul aufrufen, indem Sie die Schlüsselwörterself
odersuper
angeben.Endgültige Verzeichnisstruktur
Sie würden mit so etwas enden:
Die obige Struktur funktioniert nur ab Rust 2018. Die folgende Verzeichnisstruktur gilt auch für 2018, aber so hat 2015 funktioniert.
In dem
home/mod.rs
ist das gleiche wie./home.rs
undhome/bathroom/mod.rs
ist das gleiche wiehome/bathroom.rs
. Rust hat diese Änderung vorgenommen, da der Compiler verwirrt wäre, wenn Sie eine Datei mit demselben Namen wie das Verzeichnis einfügen würden. Die Version 2018 (die zuerst gezeigte) behebt diese Struktur.Weitere Informationen finden Sie in diesem Repo und in diesem YouTube-Video eine allgemeine Erklärung.
Eine letzte Sache ... vermeiden Sie Bindestriche! Verwenden Sie
snake_case
stattdessen.Wichtige Notiz
Sie müssen alle Dateien nach oben verschieben, auch wenn tiefe Dateien von Top-Level-Dateien nicht benötigt werden.
Dies bedeutet, dass Sie
sink.rs
sie entdeckentoilet.rs
müssen , um sie zu entdecken , indem Sie die oben genannten Methoden anwendenmain.rs
anwenden!Mit anderen Worten, tun
pub mod sink;
oder imuse self::sink;
Innerentoilet.rs
wird nicht arbeiten , es sei denn Sie haben sie den ganzen Weg bis zu ausgesetztmain.rs
!Denken Sie deshalb immer daran, Ihre Dateien nach oben zu verschieben!
quelle