Muy a menudo he obtenido un valor Option<String>
de un cálculo, y me gustaría usar este valor o un valor codificado por defecto.
Esto sería trivial con un número entero:
let opt: Option<i32> = Some(3);
let value = opt.unwrap_or(0); // 0 being the default
Pero con ay String
a &str
, el compilador se queja de tipos no coincidentes:
let opt: Option<String> = Some("some value".to_owned());
let value = opt.unwrap_or("default string");
El error exacto aquí es:
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`
Una opción es convertir el segmento de cadena en una Cadena propia, como sugiere rustc:
let value = opt.unwrap_or("default string".to_string());
Pero esto causa una asignación, lo cual no es deseable cuando quiero convertir inmediatamente el resultado de nuevo en un segmento de cadena, como en esta llamada a Regex::new()
:
let rx: Regex = Regex::new(&opt.unwrap_or("default string".to_string()));
Prefiero convertir el Option<String>
en an Option<&str>
para evitar esta asignación.
¿Cuál es la forma idomática de escribir esto?
map
no funcionó. No entiendo qué pasa con el primeroOptions<String>
y la copia que lo hace referencia en el caso de laas_deref
variante del código. Aquí está mi código de trabajo usandoas_deref
:let device_id = UsbDeviceIdentifier::VidPidSn { vid: device.vendor_id, pid: device.product_id, sn: device.serial_number.as_deref().unwrap_or("") };
y mi primer intentolet device_id = UsbDeviceIdentifier::VidPidSn { vid: device.vendor_id, pid: device.product_id, sn: device.serial_number.map(|s| s.as_str()).unwrap_or("") };
.