Есть ли рекомендуемый способ использовать `if let` со значением с плавающей точкой? - PullRequest
4 голосов
/ 04 марта 2020

Я выполняю некоторый анализ аргументов и в итоге получаю значение, равное Option<f64>, которое изначально None, но может быть Some(n), если пользователь передает программу -g n. Однако, если пользователь говорит -g 0, я получаю Some(0.0), который хочу перевести в None. Поэтому я делаю:

if let Some(0.0) = config.opt_value {
    config.opt_value = None;
}

Это кажется достаточно простым, но компилятор выдает мне предупреждение, которое я цитирую:

warning: floating-point types cannot be used in patterns
 --> src/lib.rs:2:17
  |
2 |     if let Some(0.0) = config.opt_value {
  |                 ^^^
  |
  = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>

Это сообщение направляет меня на Отслеживание Rust выпуск , который относится к Rust RF C 1445: ограничение констант в шаблонах . Существует долгая sh дискуссия, но не так много, как мы должны исправить предупреждение. RF C использует защитные приспособления для спичек для регулярного сравнения значений с плавающей точкой:

match value { n if n == 0.0 => { /* whatever */ } }

Это не работает в if let (поэтому для меня нет if let Some(n) if n == 0.0 { /* whatever */ }).

Мне удалось придумать

match config.opt_value {
    Some(n) if n == 0.0 => { config.opt_value = None },
    _ => {}
};

Это безобразно, как грех, но выполнит работу.

Есть ли рекомендуемый способ использования if let на типы с плавающей запятой в ответ на вышеупомянутое предупреждение, или мы сами по себе?

Ответы [ 2 ]

4 голосов
/ 04 марта 2020

Существует долгое sh обсуждение, но не так много, как мы должны исправить предупреждение.

Я бы просто использовал обычный не шаблон if:

    if config.opt_value == Some(0.0) {
        // ...
    }

( Детская площадка )

4 голосов
/ 04 марта 2020

Я бы использовал Option::map_or (или эквивалентные методы):

if config.opt_value.map_or(false, |v| v == 0.0)

В более широком случае я бы использовал Option::filter

let value = config.opt_value.filter(|&v| v != 0.0);

См. Также:

...