Bardzo często otrzymałem Option<String>
z obliczeń i chciałbym użyć tej wartości lub domyślnej wartości zakodowanej na stałe.
Byłoby to trywialne w przypadku liczby całkowitej:
let opt: Option<i32> = Some(3);
let value = opt.unwrap_or(0); // 0 being the default
Ale z a String
i a &str
kompilator narzeka na niezgodne typy:
let opt: Option<String> = Some("some value".to_owned());
let value = opt.unwrap_or("default string");
Dokładny błąd tutaj to:
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`
Jedną z opcji jest przekonwertowanie kawałka łańcucha na posiadany ciąg, jak sugeruje rustc:
let value = opt.unwrap_or("default string".to_string());
Ale to powoduje alokację, która jest niepożądana, gdy chcę natychmiast przekonwertować wynik z powrotem na kawałek ciągu, jak w tym wywołaniu Regex::new()
:
let rx: Regex = Regex::new(&opt.unwrap_or("default string".to_string()));
Wolałbym zamienić na Option<String>
an, Option<&str>
aby uniknąć tego przydziału.
Jaki jest idomatyczny sposób, aby to napisać?
map
nie działała. Nie rozumiem, co dzieje się z pierwszymOptions<String>
i kopią, która się do niego odwołuje w przypadkuas_deref
wariantu kodu. Oto mój działający kod przy użyciuas_deref
:let device_id = UsbDeviceIdentifier::VidPidSn { vid: device.vendor_id, pid: device.product_id, sn: device.serial_number.as_deref().unwrap_or("") };
i moja pierwsza próbalet device_id = UsbDeviceIdentifier::VidPidSn { vid: device.vendor_id, pid: device.product_id, sn: device.serial_number.map(|s| s.as_str()).unwrap_or("") };
.