Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a recommended way to use `if let` with a floating-point value?

I'm doing some argument parsing and eventually I end up with a value which is an Option<f64> which is initially None, but can be Some(n) if the user passes the program -g n. However, if the user says -g 0 I end up with a Some(0.0) which I want to translate into None. So I do:

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

That seems simple enough, but the compiler gives me a warning, which I quote:

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>

This message directs me to the Rust tracking issue, which refers to Rust RFC 1445: Restrict constants in patterns. There is a longish discussion, but not much in the way of how we are supposed to fix the warning. The RFC comes up with using match arm guards to do regular comparison on the float values:

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

This doesn't work in if let (so no if let Some(n) if n == 0.0 { /* whatever */ } for me).

I've managed to come up with

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

This is ugly as sin but will get the job done.

Is there a recommended way to use if let on floating point types in response to the above warning, or are we on our own?

like image 255
Wtrmute Avatar asked Jan 25 '23 06:01

Wtrmute


2 Answers

I'd use Option::map_or (or equivalent methods):

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

For your broader case, I'd use Option::filter

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

See also:

  • What Every Programmer Should Know About Floating-Point Arithmetic: Comparison
  • Alternatives to matching floating points
like image 83
Shepmaster Avatar answered Jan 31 '23 09:01

Shepmaster


There is a longish discussion, but not much in the way of how we are supposed to fix the warning.

I'd just use an ordinary non-pattern-matching if:

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

(Playground)

like image 32
user4815162342 Avatar answered Jan 31 '23 08:01

user4815162342