Очень часто я получаю Option<String>вычисление и хочу использовать это значение или жестко заданное значение по умолчанию.
С целым числом это было бы тривиально:
let opt: Option<i32> = Some(3);
let value = opt.unwrap_or(0); // 0 being the default
Но с a Stringи a &strкомпилятор жалуется на несовпадающие типы:
let opt: Option<String> = Some("some value".to_owned());
let value = opt.unwrap_or("default string");
Точная ошибка здесь:
error[E0308]: mismatched types
--> src/main.rs:4:31
|
4 | let value = opt.unwrap_or("default string");
| ^^^^^^^^^^^^^^^^
| |
| expected struct `std::string::String`, found reference
| help: try using a conversion method: `"default string".to_string()`
|
= note: expected type `std::string::String`
found type `&'static str`
Один из вариантов - преобразовать строковый фрагмент в принадлежащую String, как предлагает rustc:
let value = opt.unwrap_or("default string".to_string());
Но это вызывает выделение, что нежелательно, когда я хочу немедленно преобразовать результат обратно в строковый фрагмент, как в этом вызове Regex::new():
let rx: Regex = Regex::new(&opt.unwrap_or("default string".to_string()));
Я предпочел бы преобразовать Option<String>в , Option<&str>чтобы избежать этого распределения.
Как это идоматически написать?
mapне сработала. Я не понимаю, что происходит с первойOptions<String>и той копией, которая на нее ссылается в случаеas_derefварианта кода. Вот мой рабочий код, использующийas_deref:let device_id = UsbDeviceIdentifier::VidPidSn { vid: device.vendor_id, pid: device.product_id, sn: device.serial_number.as_deref().unwrap_or("") };и моя первая попыткаlet device_id = UsbDeviceIdentifier::VidPidSn { vid: device.vendor_id, pid: device.product_id, sn: device.serial_number.map(|s| s.as_str()).unwrap_or("") };.