2016-11-14 3 views
6

Ich möchte ein Makro schreiben, das" OK "ausgibt und dann self in einer Methode zurückgibt. Es ist mein erstes Makro, so habe ich versucht, diese, dachte, es wird nur so etwas wie ein Text Ersatz machen, aber es funktioniert nicht:Kann nicht self in Makro verwenden, da die Makroerweiterung das Token `self` ignoriert

macro_rules! print_ok_and_return_self { 
    () => { 
     println!("OK"); 
     self 
    } 
} 

fn main() { 
    let a = A{}; 
    a.a().a(); 
} 

struct A {} 

impl A { 
    fn a(self) -> Self { 
     print_ok_and_return_self!() 
    } 
} 

Fehler:

error: macro expansion ignores token `self` and any following 
--> src/main.rs:4:13 
    | 
4 |    self 
    |    ^^^^ 
    | 
note: caused by the macro expansion here; the usage of `print_ok_and_return_self!` is likely invalid in expression context 
--> src/main.rs:17:13 
    | 
17|    print_ok_and_return_self!() 
    |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

Nach einem kurzen Blick auf die Dokumentation, I Ich weiß, dass es nicht nur ein Ersatz für Text ist, aber ich weiß immer noch nicht, wie es funktioniert.

Antwort

12

Es gibt zwei Fehler hintereinander, lassen Sie uns die erste beheben.

Die Syntax für einen Makro-Arm ist:

(...) => { 
    ... 
} 

was bedeutet, dass das, was aufwendet Ihr Makro ist:

println!("OK"); 
self 

, die nicht in Ordnung ist (zwei Aussagen).

Stattdessen sollte es zu einem Ausdruck (in diesem Fall) erweitern, die Sie durch Einschließen innerhalb {} erhalten:

macro_rules! print_ok_and_return_self { 
    () => { 
     { 
      println!("OK"); 
      self 
     } 
    } 
} 

Dies führt zum zweiten Fehler:

error[E0424]: `self` is not available in a static method 
    --> <anon>:4:9 
    | 
4 |   self 
    |   ^^^^ not available in static method 
... 
17 |   print_ok_and_return_self!() 
    |   --------------------------- in this macro invocation 
    | 
    = note: maybe a `self` argument is missing? 

Ein Makro kann nicht die Existenz einer Variablen in ihrem Gültigkeitsbereich annehmen, daher müssen Sie self als Argument übergeben:

macro_rules! print_ok_and_return_value { 
    ($v:expr) => {{ 
     println!("OK"); 
     $v 
    }} 
} 

und der Aufruf wird:

impl A { 
    fn a(self) -> Self { 
     print_ok_and_return_value!(self) 
    } 
} 
Verwandte Themen