2016-08-18 2 views
3

In meinem Programm vertrete ich eine Geschichte von Änderungen an Feldern einiger Objekte wie folgt:Gibt es ein Analog von nameof() von C# in Rust?

struct FieldChange { 
    property_name: &'static str, 
    // some other fields 
} 

let history = Vec<FieldChange>::new(); 

ich es so handhaben:

match field_change.property_name { 
    "name" => // do something, 
    "age" => // do something, 
    _  => {} 
} 

mit Lesbarkeit zu verbessern und zukünftige Refactoring erleichtern, I so etwas wie dies möchte schreiben:

match field_change.property_name { 
    nameof(Person::name) => // do something, 
    nameof(Person::age) => // do something, 
    _     => {} 
} 

wo nameof erzeugt ein &str Vertre ähnlich wie nameof in C#.

Der wichtigste Punkt ich suche, ist, dass der Compiler überprüfen kann, ob die Felder vorhanden sind (beispielsweise in diesem Fall, ob Person tatsächlich name und age Felder hat). Ist es möglich, die Feldnamen in Rust so zu extrahieren?

Antwort

3

Nein, aber Sie können etwas vergleichbar mit Makros bekommen. Weil Makros alles lösen![1]

macro_rules! name_of { 
    ($name:ident in $ty:ty) => { 
     { 
      #[allow(dead_code)] 
      fn dummy(v: $ty) { 
       let _ = &v.$name; 
      } 
      stringify!($name) 
     } 
    }; 

    ($name:ident) => { 
     { 
      let _ = &$name; 
      stringify!($name) 
     } 
    }; 
} 

struct Person { 
    // 255 years should be enough for anybody. 
    age: u8, 
    name: String, 
} 

fn main() { 
    let p = Person { age: 27, name: "John Smith".into() }; 
    println!("The {} of Person {} is: {}", name_of!(age in Person), name_of!(p), p.age); 
} 

Wenn Sie versuchen, einen Namen zu verwenden, ist nicht vorhanden, bekommen etwas, das wie folgt aussieht:

error: unresolved name `q`. Did you mean `p`? [--explain E0425] 
    --> <anon>:28:78 
28 |>  println!("The {} of Person {} is: {}", name_of!(age in Person), name_of!(q), p.age); 
    |>                   ^

Oder wie folgt aus:

error: attempted access of field `shoe_size` on type `Person`, but no field with that name was found 
--> <anon>:6:26 
6 |>     let _ = &v.$name; 
    |>      ^

[1]: Hinweis: Makros lösen tatsächlich nicht alles.

+0

Danke für die Antwort. Leider funktioniert dieser Trick nicht mit dem Mustervergleich. Ich nehme an, dass prozedurale Makros mir helfen könnten, wenn es dazu kommt – xilec

+0

Ah, richtig; Ich habe den 'match' Teil vergessen. Ich kann nichts dagegen tun: Wenn Sie den Namen * exists * geltend machen wollen, müssen Sie etwas tun, das es verwendet, und Sie können das nicht innerhalb eines Musters tun. Und nein, prozedurale Makros * werden nicht helfen, weil sie die gleichen Einschränkungen wie reguläre Makros haben: * sie können Namen nicht sehen *. Sie hätten etwas ähnliches ausstrahlen müssen. –

Verwandte Themen