Очень часто я получаю 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("") };
.