Rust Makros. Makros operieren auf der syntaktischen Ebene, nicht auf der semantischen Ebene. Das bedeutet, obwohl der Compiler weiß, dass er einen Ausdruck (Syntax) hat, weiß er nicht, was der Wert des Ausdrucks (semantisch) in dem Moment ist, in dem das Makro expandiert wird.
Eine Abhilfe wäre die erwartete Art an das Makro weitergeben müssen:
macro_rules! attribute {
($e:expr, f32) => { /* magical float stuff */ };
($e:expr, i64) => { /* mystical int stuff */ };
}
fn main() {
attribute!(2 + 2, i64);
}
Oder, einfacher gesagt, mehrere Makros definieren.
Wenn Sie statische (kompilieren Zeit) Versendung auf dem Typ eines Ausdrucks basierend tun möchten, können Sie Merkmale verwenden. Definieren Sie ein Merkmal mit den erforderlichen Methoden und implementieren Sie dann das Merkmal für die von Ihnen benötigten Typen. Sie können ein Merkmal für beliebigen Typ (einschließlich Grundelemente und Typen aus anderen Bibliotheken) implementieren, wenn der impl
Block in der gleichen Kiste wie die Merkmaldefinition ist.
trait Attribute {
fn process(&self);
}
impl Attribute for f32 {
fn process(&self) { /* TODO */ }
}
impl Attribute for i64 {
fn process(&self) { /* TODO */ }
}
macro_rules! attribute {
($e:expr) => { Attribute::process(&$e) };
}
fn main() {
attribute!(2 + 2);
}
Hinweis: Sie können auch $e.process()
im Makro Körper schreiben könnte, aber dann das Makro möglicherweise eine unabhängige process
Methode aufrufen.
Makros nur Versand auf Syntax, traits OTOH Versand kann die Art basiert. Ziehen Sie in Erwägung, ein Merkmal zu verwenden oder ein Merkmal in Ihrem Makro zu verwenden. – bluss