2016-06-03 3 views
1

Я работаю на Exercism упражнения, и я столкнулся с этим:Обучение Ржавчина и документация

fn test_no_allergies_means_not_allergic() { 
    let allergies = Allergies::new(0); 
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Peanuts)); 
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Cats)); 
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Strawberries)); 
} 

Когда я смотрю на Allergen::Peanuts, я думаю, что это символ, как Ruby, но я могу» t найти что-нибудь в документации об этом, кроме идеи ящиков и модулей. Я не могу думать, что Allergen представляет собой модуль с отдельными ящиками в основном потому, что README приводит меня к этому:

Перечень элементов (и их значения), которые были проверены, являются:

  • яйца (1)
  • арахиса (2)
  • моллюски (4)
  • клубники (8)
  • помидоры (16)
  • шоколад (32)
  • пыльцевые (64)
  • кошек (128)

Так что если Том аллергия на арахис и шоколад, он получает оценку 34.

Это должно быть какое-то перечисление с каждым из этих значений и какой-то битовой маской, но я просто не могу найти документацию, чтобы показать мне больше о символах. Я не хочу сдаваться, и я хочу как можно больше узнать о Rust, но документам не хватает.

Есть ли какие-либо предложения относительно перечислений, объектов, символов и где я могу получить дополнительную документацию относительно ржавчины?

ответ

0

Ржавчина не имеет типа битов в языке или стандартной библиотеке. Но есть bitflags клеть, который вы могли бы написать

#[macro_use] extern crate bitflags; 

bitflags! { 
    flags Allergies: u32 { 
     const ALLERGEN_EGGS = 1, 
     const ALLERGEN_PEANUTS = 2, 
     ... 
     const ALLERGEN_CATS = 128, 
    } 
} 

impl Allergies { 
    pub fn is_allergic_to(&self, other: &Allergies) -> bool { 
     self.intersects(*other) 
    } 
} 

let allergies = Allergies::empty(); 
assert!(!allergies.is_allergic_to(&ALLERGEN_CATS)); 
//^unfortunately we don't support associated constants 
// so we have to name it ALLERGEN_CATS instead of Allergies::CATS. 
assert_eq!((ALLERGEN_PEANUTS | ALLERGEN_CHOCOLATE).bits(), 34); 

Не забудьте добавить bitflags раздел в вашем Cargo.toml [dependency].


Если вы не хотите зависеть от внешнего ящика, вы можете основывать свой тип на целочисленных типах вместе с поразрядными операциями. They are the same as Cисключая что мы используем ! вместо ~ для побитового-нет.

Константы должны быть определены в separate module:

#[allow(non_upper_case_globals)] // <- silence 8 warnings 
mod Allergen { 
    pub const Eggs: u32 = 1; // <- use a new type if you like 
    pub const Peanuts: u32 = 2; 
    ... 
    pub const Cats: u32 = 128; 
} 

или как C-типа перечисления (ассоциированные члены перечислений с explicit discriminants):

enum Allergen { 
    Eggs = 1, 
    Peanuts = 2, 
    ... 
    Cats = 128, 
} 

let score = (Allergen::Peanuts as isize) | (Allergen::Chocolate as isize); 

Оба из которых не передают концепция, что значения образуют битовые флагов. Серьезно, вам следует избегать этих обходных меток, если вы можете использовать внешние ящики.

+0

Я знаю, как использовать битовую маску и имеет сдвиг бит, который позволяет сравнивать одно из значений констант.Я думал о списке констант, но думал, что что-то немного лучше. А также, вы, константы, не соответствуют тесту вообще. Я не могу изменить тесты, поэтому Allergen :: Peanuts - это то, как, к сожалению, нужно заявить, что это не змеиный случай. Но спасибо. – macshaggy

+0

@macshaggy: Как я уже сказал, Rust не поддерживает битовые флаги изначально. (Вы можете попробовать [C-style enum] (http://rustbyexample.com/custom_types/enum/c_like.html), но они не работают как бит-флаги.) – kennytm

+0

@macshaggy Если вы используете ящики 'bitflags' константы должны быть названы LIKE_THIS, потому что они определены как константы модуля, и это стандартное соглашение об именах. Вы могли бы назвать это «Кошки» сделать «mod Allegens {pub use {Cats, ...}}', но это уродливо :). – kennytm

Смежные вопросы