3

I have written some code that parses a config file. If the config file holds a valid value for a field it sets in Config struct. If no valid integer value was found for a setting it sets a default value (e.g: 90).

let config = Config {
    interval: settings.get("interval").unwrap().parse().unwrap_or(90),
}

How can I make this to take a closure, so that it can print via error! and set default value?

Looking something like following:

let config = Config {
    interval: settings.get("interval").unwrap().parse().unwrap_or({
        error!("No interval found. Using default: 90");
        90
    });
}

But in this example, the error! is always executed, even if a valid value from interval was read from the config.

How can I make it so that unwrap_or only executes the code in optb when parse() has failed?

Lukas Kalbertodt
  • 79,749
  • 26
  • 255
  • 305
Robin van Leeuwen
  • 2,625
  • 3
  • 24
  • 35

1 Answers1

10

How can I make it so that unwrap_or only executes the code in optb when parse() has failed?

  • Arguments passed to unwrap_or are eagerly evaluated.

  • If you are passing the result of a function call, it is recommended to use unwrap_or_else which is lazily evaluated.

In your scenario it should be changed as following:

let config: Config = Config {
   interval: settings.get("interval").unwrap().parse().unwrap_or_else(|_| {
        error!("No interval found. Using default: 90");
        90
    }),
}

Playground


Also you should not use naked unwrap() in your production code. Error handling is better solution instead of using naked unwrap()

Here you can find detailed info about why you should not use unwrap()

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Akiner Alkan
  • 6,145
  • 3
  • 32
  • 68
  • Ahh, easy enough. This was what i was looking for. I'll read up on the differences between the _or() and _or_else() functions. I suspect the _ in this will be the error on which the parse failed? – Robin van Leeuwen Feb 13 '19 at 06:39
  • Yes exactly, To keep the answer minimal, I did not handle the error in the answer, just silenced it with underscore – Akiner Alkan Feb 13 '19 at 06:42
  • 2
    The issue of `unwrap()` is a bit more nuanced than "don't panic in production". The answers to the linked question are a pretty good starting point. I'd guess that @Robin may want to treat the absence of an `"interval"` field the same way as an unparseable value, in which case one way to do that would be `.and_then(|value| value.parse().ok())` instead of `.unwrap().parse()`. – trent Feb 13 '19 at 08:04