将借来的值嵌入到枚举中?
Embedding a borrowed value into an enum?
我在使用以下代码时遇到困难:
trait HelloPhrase {
fn hello(&self, to: &'static str);
}
pub enum GetHelloResult<H: HelloPhrase> {
Matched(H),
NoMatch,
}
struct English;
impl English {
pub fn new() -> English {
English
}
}
impl HelloPhrase for English {
fn hello(&self, to: &'static str) {
println!("Hello {}.", to)
}
}
struct Phrases<H: HelloPhrase> {
hello_phrases: std::collections::HashMap<&'static str, H>,
}
impl<H: HelloPhrase> Phrases<H> {
pub fn new() -> Phrases<H> {
Phrases { hello_phrases: std::collections::HashMap::new() }
}
pub fn add_hello_phrase(&mut self, lang: &'static str, hello_phrase: H) {
self.hello_phrases.insert(lang, hello_phrase);
}
pub fn get_hello(&self, lang: &'static str) -> GetHelloResult<H> {
match self.hello_phrases.get(lang) {
Some(hello_phrase) => return GetHelloResult::Matched(hello_phrase),
_ => return GetHelloResult::NoMatch,
};
}
}
fn main() {
let mut hs = Phrases::new();
hs.add_hello_phrase("english", English::new());
match hs.get_hello("english") {
GetHelloResult::Matched(hello_phrase) => hello_phrase.hello("Tom"),
_ => println!("HelloPhrase not found"),
}
}
HelloPhrase
是要实现的语言的特征,英语、俄语等。 Phrases
是一个管理器结构,它可以有许多语言到短语的映射。这是一个人为的示例,但您可以将其视为事件管理器(即获取 X 输入的事件处理程序)或 HTTP 处理程序和路由器。
话虽如此,我很难理解如何将 HelloPhrase
到 return 的所有权借给调用者。 运行它,return出现以下错误:
<anon>:40:66: 40:78 error: mismatched types:
expected `H`,
found `&H`
(expected type parameter,
found &-ptr) [E0308]
<anon>:40 Some(hello_phrase) => return GetHelloResult::Matched(hello_phrase),
^~~~~~~~~~~~
我试过添加:
pub fn get_hello(&self, lang: &'static str) -> GetHelloResult<&H> {
和
pub enum GetHelloResult<H: HelloPhrase> {
Matched(&H),
NoMatch,
}
这会导致以下错误:
<anon>:7:13: 7:15 error: missing lifetime specifier [E0106]
<anon>:7 Matched(&H),
我在向枚举添加生命周期时遇到问题 - 理论上我希望 returned 值的生命周期是 Phrases
结构的生命周期 - 但生命周期语法相当到目前为止让我感到困惑。总结为两个问题:
- 如何向
GetHelloResult
添加生命周期以满足此错误?
- 基于 Rust 的所有权规则,我正在尝试用 Rust 做一个反模式吗?对于这样的事情,什么可能是更好的设计?
根据文档,我知道如何在结构上使用生命周期,但我不知道如何将生命周期添加到枚举(语法方面)。我只提到了 struct lifetime,因为我认为这是一个缺失的部分,但老实说我不知道。此外,如果我向结构和 impl 添加生命周期并尝试将其添加到 hello_phrases
映射,我会收到错误
the parameter type `H` may not live long enough [E0309]
这里的混淆是生命周期省略的一个不幸的副作用。它在 99% 的情况下都有帮助,但不是很容易被发现。
您需要用生命周期注释GetHelloResult
:
pub enum GetHelloResult<'a, H: 'a + HelloPhrase> {
Matched(&'a H),
NoMatch,
}
pub fn get_hello(&self, lang: &'static str) -> GetHelloResult<H> {
match self.hello_phrases.get(lang) {
Some(hello_phrase) => return GetHelloResult::Matched(hello_phrase),
_ => return GetHelloResult::NoMatch,
};
}
这将 GetHelloResult
的生命周期与 Phrases
结构的生命周期联系起来,因此如果 Phrases
结构发生突变(或破坏!),返回的引用将作废。在这种情况下,生命周期被推断为与 self
相同,这在阅读时并不明显,但确实如此!在不太明显的情况下,您可能希望使用 GetHelloResult<'a, H>
.
显式注释
当您 return 一个引用 (fn get_hello(&self, lang: &'static str) -> GetHelloResult<&H>
) 时代码工作正常,只要您实现对也实现该特征的类型的引用的特征:
impl<'a, H> HelloPhrase for &'a H
where H: HelloPhrase
{
fn hello(&self, to: &'static str) {
(**self).hello(to)
}
}
我在使用以下代码时遇到困难:
trait HelloPhrase {
fn hello(&self, to: &'static str);
}
pub enum GetHelloResult<H: HelloPhrase> {
Matched(H),
NoMatch,
}
struct English;
impl English {
pub fn new() -> English {
English
}
}
impl HelloPhrase for English {
fn hello(&self, to: &'static str) {
println!("Hello {}.", to)
}
}
struct Phrases<H: HelloPhrase> {
hello_phrases: std::collections::HashMap<&'static str, H>,
}
impl<H: HelloPhrase> Phrases<H> {
pub fn new() -> Phrases<H> {
Phrases { hello_phrases: std::collections::HashMap::new() }
}
pub fn add_hello_phrase(&mut self, lang: &'static str, hello_phrase: H) {
self.hello_phrases.insert(lang, hello_phrase);
}
pub fn get_hello(&self, lang: &'static str) -> GetHelloResult<H> {
match self.hello_phrases.get(lang) {
Some(hello_phrase) => return GetHelloResult::Matched(hello_phrase),
_ => return GetHelloResult::NoMatch,
};
}
}
fn main() {
let mut hs = Phrases::new();
hs.add_hello_phrase("english", English::new());
match hs.get_hello("english") {
GetHelloResult::Matched(hello_phrase) => hello_phrase.hello("Tom"),
_ => println!("HelloPhrase not found"),
}
}
HelloPhrase
是要实现的语言的特征,英语、俄语等。 Phrases
是一个管理器结构,它可以有许多语言到短语的映射。这是一个人为的示例,但您可以将其视为事件管理器(即获取 X 输入的事件处理程序)或 HTTP 处理程序和路由器。
话虽如此,我很难理解如何将 HelloPhrase
到 return 的所有权借给调用者。 运行它,return出现以下错误:
<anon>:40:66: 40:78 error: mismatched types:
expected `H`,
found `&H`
(expected type parameter,
found &-ptr) [E0308]
<anon>:40 Some(hello_phrase) => return GetHelloResult::Matched(hello_phrase),
^~~~~~~~~~~~
我试过添加:
pub fn get_hello(&self, lang: &'static str) -> GetHelloResult<&H> {
和
pub enum GetHelloResult<H: HelloPhrase> {
Matched(&H),
NoMatch,
}
这会导致以下错误:
<anon>:7:13: 7:15 error: missing lifetime specifier [E0106]
<anon>:7 Matched(&H),
我在向枚举添加生命周期时遇到问题 - 理论上我希望 returned 值的生命周期是 Phrases
结构的生命周期 - 但生命周期语法相当到目前为止让我感到困惑。总结为两个问题:
- 如何向
GetHelloResult
添加生命周期以满足此错误? - 基于 Rust 的所有权规则,我正在尝试用 Rust 做一个反模式吗?对于这样的事情,什么可能是更好的设计?
根据文档,我知道如何在结构上使用生命周期,但我不知道如何将生命周期添加到枚举(语法方面)。我只提到了 struct lifetime,因为我认为这是一个缺失的部分,但老实说我不知道。此外,如果我向结构和 impl 添加生命周期并尝试将其添加到 hello_phrases
映射,我会收到错误
the parameter type `H` may not live long enough [E0309]
这里的混淆是生命周期省略的一个不幸的副作用。它在 99% 的情况下都有帮助,但不是很容易被发现。
您需要用生命周期注释GetHelloResult
:
pub enum GetHelloResult<'a, H: 'a + HelloPhrase> {
Matched(&'a H),
NoMatch,
}
pub fn get_hello(&self, lang: &'static str) -> GetHelloResult<H> {
match self.hello_phrases.get(lang) {
Some(hello_phrase) => return GetHelloResult::Matched(hello_phrase),
_ => return GetHelloResult::NoMatch,
};
}
这将 GetHelloResult
的生命周期与 Phrases
结构的生命周期联系起来,因此如果 Phrases
结构发生突变(或破坏!),返回的引用将作废。在这种情况下,生命周期被推断为与 self
相同,这在阅读时并不明显,但确实如此!在不太明显的情况下,您可能希望使用 GetHelloResult<'a, H>
.
当您 return 一个引用 (fn get_hello(&self, lang: &'static str) -> GetHelloResult<&H>
) 时代码工作正常,只要您实现对也实现该特征的类型的引用的特征:
impl<'a, H> HelloPhrase for &'a H
where H: HelloPhrase
{
fn hello(&self, to: &'static str) {
(**self).hello(to)
}
}