2017-01-11 10 views
6

Próbuję dopasować na typ danych ogólnego pola struktury i odpowiednio reagować. Moja ogólna idea była tak (kod nie skompilować):Jak dopasować typ danych w Rust?

struct foo<T> { 
    zaz: String, 
    bar: T, 
} 

fn main() { 
    let x = foo::<String> { 
     zaz: "Hello".to_string(), 
     bar: "world".to_string(), 
    }; 
    let y = foo::<u32> { 
     zaz: "Hello".to_string(), 
     bar: 5, 
    }; 

    match x.bar { 
     String => println!("It's a string!"), 
     u32 => println!("It's a u32!"), 
     _ => println!("Something else"), 
    }; 

    println!("end of program!"); 
} 

Komunikat o błędzie od rustc:

error[E0001]: unreachable pattern 
    --> src/main.rs:18:9 
    | 
18 |   u32 => println!("It's a u32!"), 
    |   ^^^ this is an unreachable pattern 
    | 
note: this pattern matches any value 
    --> src/main.rs:17:9 
    | 
17 |   String => println!("It's a string!"), 
    |   ^^^^^^ 

error[E0001]: unreachable pattern 
    --> src/main.rs:19:9 
    | 
19 |   _ => println!("Something else"), 
    |  ^this is an unreachable pattern 
    | 
note: this pattern matches any value 
    --> src/main.rs:17:9 
    | 
17 |   String => println!("It's a string!"), 
    |   ^^^^^^ 

Chciałem było dla x dopasować pierwszy i y dopasować Druga. W rzeczywistości nie jestem pewien, co chcę zrobić, ale co by osiągnąć pożądany efekt?

+0

Krótka odpowiedź brzmi „nie tuż nietoperza”. Przydatne może się okazać to pytanie: [W jaki sposób Rust implementuje odbicie?] (Http://stackoverflow.com/q/36416773/1233251) –

+0

Rust używa nazwy "CamelCase" do konstrukcji, wyliczenia i cech. Powinieneś używać 'Foo'. – Shepmaster

Odpowiedz

8

Idiomatic Rozwiązanie

Stwórz cechę zmusza parametr T w foo, wdrożyć żadnego konkretnego zachowania jako powiązanej funkcji tej cechy.

Przykład:

trait PrintMe { 
    fn print_me(&self); 
} 

impl PrintMe for String { 
    fn print_me(&self) { println!("I am a string"); } 
} 

struct Foo<T: PrintMe> { 
    zaz: String, 
    bar: T 
} 

fn main() { 
    // ... 
    x.bar.print_me(); 
} 

To pryncypialny rodzajowe programowania, w którym deklarują dokładnie różnicę zachowań możliwych parametrów ogólnych, tak, że nie ma nic dziwnego.


dokładne rozwiązanie

Rdza może rzeczywiście kwerendy typy: każdy rodzaj ma unikalną TypeId powiązanych, można dopasować na TypeId z serii if kontroli. Jest niezgrabny.

fn print_me<T>(x: &Foo<T>) { 
    if TypeId::of::<T>() == TypeId::of::<String>() { 
     println!("I am a string"); 
    } else // ... 
} 

Ale proszę ... nie rób tego :)

+0

Dziękuję, Matthieu. To oczyszcza sprawy. Myślę, że muszę zmienić ogólnie mój projekt, wciąż układam swój kod w stylu "C". Dzięki! – Dash83

+0

+1 dla "nie rób tego", a powiem tylko, że Rust * ma * "wyliczenie", co jest lepszym (krótszym, jaśniejszym, idiomatycznym i sprawdzonym przez kompilację) sposobem napisania tych wszystkich " TypeId :: of' checks. – trentcl

+0

@trentcl: To zależy. 'enum' jest dla polimorfizmu zamkniętego, podczas gdy' cecha 'jest dla otwartego polimorfizmu ... jeśli to ma sens. –