是否可以在 Rust 中创建一个接受Option<String>
或Option<&str>
作为参数的函数? 这是我的测试,但编译器报告错误。
#![allow(unused_variables)]
#![allow(dead_code)]
struct Person {
name: String,
}
impl Person {
fn new<S: Into<Option<String>>>(name: S) -> Person {
Person { name: name.into().unwrap_or("unknown".to_string()) }
}
}
fn main() {
let person1 = Person::new(Some("Test"));
let person2 = Person::new(Some("Test".to_string()));
}
我认为你想得到一个Option
,但有不同的内在类型。函数签名应反映:
fn new<S: ToString>(name: Option<S>) -> Person {}
我将泛型类型从Into<String>
更改为ToString
ToString
因为"对于实现显示特征的任何类型自动实现",并且您的函数可以接受更多不同的类型。
由于有Option
我将进行如下操作:
将Option
的内部类型 (S
) 转换为String
name.map(|name| name.to_string()
使用默认值解开选项的包装
.unwrap_or_else(|| "unknown".to_string())
我使用unwrap_or_else
而不是unwrap_or
,因为即使Option
Some
unwrap_or
调用函数to_string
,但只有在Option
None
时才unwrap_or_else
。
完整代码:
fn new<S: ToString>(name: Option<S>) -> Person {
Person {
name: name
.map(|name| name.to_string())
.unwrap_or_else(|| "unknown".to_string()),
}
}
的测试,但编译器报告错误。
提醒:Rust 的编译器是一个相当有帮助的家伙,当它抱怨阅读错误是有用的,当你寻求帮助时,发布这些错误对读者也很有用。
这里的错误相当明显:
error[E0277]: the trait bound `Option<String>: From<Option<&str>>` is not satisfied
--> src/main.rs:14:31
|
14 | let person1 = Person::new(Some("Test"));
| ----------- ^^^^^^^^^^^^ the trait `From<Option<&str>>` is not implemented for `Option<String>`
| |
| required by a bound introduced by this call
|
= help: the following implementations were found:
<Option<&'a T> as From<&'a Option<T>>>
<Option<&'a mut T> as From<&'a mut Option<T>>>
<Option<T> as From<T>>
这意味着没有Option
->Option
通过From
/Into
实现,所以这是一个死胡同。
但是由于Option
是一个具体的类型,你实际上不需要从Option<A>
到Option<B>
的"内置"转换,相反,你可以只使用Option::map
并调用现有的A -> B
转换函数:
Person { name: name.map(Into::into).unwrap_or("unknown".to_string()) }
顺便说一下,有一种类型几乎是为此制作的(不是Option
位,而是"可能是字符串或引用Cow
。
顺便说一下:a.unwrap_or(b.to_string())
是相当糟糕的风格(clippy警告不要这样做):因为Rust是一种渴望的语言,所以它总是会分配一个字符串,即使在已经有一个字符串的情况下也是如此。