2017-05-17 4 views
0

Ich habe einige sich wiederholende CodeWie Makro für ähnliche passende Arme schreiben?

match *x { 
    A(ref a) => "special", 
    B(ref a) => "B foo", 
    C(ref a) => "C foo", 
    D(ref a) => "D foo", 
    // ... 
} 

ich ein Makro wie

macro_rules! generic_fmt { 
    ($T:ident) => { 
     $T(ref a) => {"$T foo"}, 
    } 
} 

möchte also, dass ich meine Anpassung an

vereinfachen
match *x { 
    A(ref a) => "special", 
    generic_fmt!(B), 
    generic_fmt!(C), 
    generic_fmt!(D), 
    // ... 
} 

Was ist der beste Weg, das zu tun? Ich benutze rustc 1.19.0-Nacht.

Antwort

2

Wenn Ihre Ausgabe ein wenig akzeptabel zu ändern, können Sie einen Sammelbegriff für alle die gleichen Waffen benutzen konnten:

match x { 
    Foo::A(ref a) => println!("special"), 
    _ => println!("{:?} Foo", x), 
} 

Playground link

Aber das würde den Typ und seine Parameter drucken. Wenn Sie jede Nacht eingeschaltet sind und keine Angst vor Experimenten haben, können Sie std::intrinsics::type_name verwenden, um nur den Typnamen anzuzeigen.

Oder können Sie ein Makro verwenden, die alle tut Ihr Spiel Arme:

macro_rules! gen_match { 
    ($x:ident, $Special:ident, [$($Foo:ident),*]) => { 
     match $x { 
      Foo::$Special(ref a) => println!("special"), 
      $(Foo::$Foo(ref a) => println!("{} foo", stringify!($Foo)),)* 
     } 
    } 
} 

und nannte es:

gen_match!(x, A, [B, C, D]); 

Playground link

Die Klammern um die Varianten, die formatiert generisch sein wird sind für die Lesbarkeit, könnten sie aus der Makrodefinition entfernt werden

+0

Wie kann ich benutze 'type_name'? Es gibt mir nur die Art von "Enum", nicht den einzelnen Gegenstand? http://play.integer32.com/?gist=b015089c2a81fe44724eea5c4ce006bc&version=undefined – colinfang

+1

Oh 'type_name' funktioniert nicht, wie ich für' Enum' ... Sie können versuchen https://github.com/mockersf/variant- Name, es hat Spaß gemacht zu schreiben –

1

Sie können das nicht genau tun. Ein Makro kann nicht zu einem match-Arm (<Variant> => <Expression>) erweitert werden.

Die nächstgelegene Sie bekommen könnte, ist wahrscheinlich so etwas wie folgt aus:

enum Foo { 
    A(u32), 
    B(u32), 
    C(u32), 
    D(u32), 
} 

macro_rules! gen1 { 
    ($Variant:ident) => { 
     Foo::$Variant(ref a) 
    } 
} 

macro_rules! gen2 { 
    ($Variant:ident) => { 
     concat!(stringify!($Variant), " foo") 
    } 
} 

fn print(x: Foo) { 
    println!("{}", match x { 
     Foo::A(ref a) => "special", 
     gen1!(B) => gen2!(B), 
     gen1!(C) => gen2!(C), 
     gen1!(D) => gen2!(D), 
    }); 
} 

fn main() { 
    print(Foo::A(42)); 
    print(Foo::B(42)); 
    print(Foo::C(42)); 
    print(Foo::D(42)); 
} 

Playground link.