gpt4 book ai didi

rust - 将具有相同泛型的相同结构的枚举匹配

转载 作者:行者123 更新时间:2023-11-29 08:31:08 24 4
gpt4 key购买 nike

我有这样一个例子:

pub enum Foo {
Foo1(Foo1),
Foo2(Foo2),
Foo3(Foo3),
}

在哪儿
pub type Foo1 = Bar<I1>;
pub type Foo2 = Bar<I2>;

在哪儿
struct Bar<I>{
var: I,
...
}

impl Bar{
fn do(word: &str){
...
}


在这里,我正在编写另一个需要 match块的函数:
match something {
Foo::Foo1(inner) => {
inner.do(a_word)
}
Foo::Foo2(inner) => {
inner.do(a_word)
}
_ => {
(...)
}
}

innerBar结构,但在 Foo1Foo2中不同:
inner用于 Foo1Bar<I1>
inner用于 Foo2Bar<I2>
问题是,在上面的块中, something匹配 Foo1Foo2时的操作是完全相同的,但是重复两次相同的操作不是很优雅。
我试过:
match something {
Foo::Foo1(inner) | Foo::Foo2(inner)=> {
inner.do(a_word)
_ => {
(...)
}
}

它不起作用,因为 innerFoo1中的 Foo2是不同类型的(如前所述)
那么我怎样才能把 Foo1Foo2紧密地匹配起来呢?
谢谢您!

最佳答案

我假设有时您希望对Foo项运行相同的操作,而不考虑变量,而有时您希望根据变量更改逻辑。对于第二种情况,我不认为有任何方法可以绕过匹配块,或者,如果您只关心一个变量,则可以使用类似的方法:

if let Foo::Foo1(inner) = &foo {
&inner.do_something(a_word);
}

(我更改了您的函数名,以避免保留关键字“do”。)
对于第一种情况,不管Foo枚举的变量是什么,您经常要执行相同的操作,您能在Foo中创建一些helper函数吗?例如,这将获得对所有变体的内部 Bar<I>的引用:
fn get_inner(&self) -> &Bar<I> {
match self {
Foo::Foo1(inner) | Foo::Foo2(inner) | Foo::Foo3(inner) => inner,
}
}

你可以这样称呼它:
foo.get_inner().do_something(a_word);

只有当Foo的每个变体都有一个Bar时,这才有效。否则,可以将get_inner()的返回类型更改为 Option<&Bar<I>>
如果有几个不同的函数需要调用,可以创建一些帮助函数,使您可以调用函数,而不必考虑Foo的变体,例如:
fn run(&self, value: &str, f: &Fn(&Bar<I>, &str) -> ()) {
f(self.get_inner(), value);
}

本例中的签名是f是 Bar<I>上的一个方法,它引用一个字符串片段。可以这样称呼:
foo.run(a_word, &Bar::do_something);

但要调用的特定函数可以在运行时计算出来,只要它与签名匹配。如果只有Foo的一些变体有一个内部条,那么可以将run()更改为仅在有条可以调用函数时才调用该函数。
下面是完整的代码示例,我对您要做的事情做了很多假设:
#![allow(dead_code)]

fn main() {
match_enum();
}

pub type Foo1<I1> = Bar<I1>;
pub type Foo2<I2> = Bar<I2>;
pub type Foo3<I3> = Bar<I3>;

pub struct Bar<I> {
var: I,
}

impl<I> Bar<I> {
fn do_something(&self, word: &str) {
println!("\nBar.do_something(): {}", word);
}
}

pub enum Foo<I> {
Foo1(Foo1<I>),
Foo2(Foo2<I>),
Foo3(Foo3<I>),
}

impl<I> Foo<I> {
fn get_inner(&self) -> &Bar<I> {
match self {
Foo::Foo1(inner) | Foo::Foo2(inner) | Foo::Foo3(inner) => inner,
}
}

fn run(&self, value: &str, f: &Fn(&Bar<I>, &str) -> ()) {
f(self.get_inner(), value);
}
}

fn match_enum() {
let a_word = "abc";
let foo = Foo::Foo1(Bar { var: "foo1_bar" });

// Call a function only for certain variants of Foo:
match &foo {
Foo::Foo1(inner) => {
&inner.do_something(a_word);
}
Foo::Foo2(inner) => {
&inner.do_something(a_word);
}
_ => {}
}

// Call a function only for one variant of Foo:
if let Foo::Foo1(inner) = &foo {
&inner.do_something(a_word);
}

// Call a function regardless of the variant of Foo:
foo.get_inner().do_something(a_word);

// As above but using a function that could have been chosen
// at runtime:
foo.run(a_word, &Bar::do_something);

}

埃塔:我想我漏掉了一些东西,因为我上面写的方式很好:
match &foo {
Foo::Foo1(inner) | Foo::Foo2(inner) => {
&inner.do_something(a_word);
}
_ => {}
}

但是在您的文章中,您说等效的代码不起作用,这意味着 inner在Foo1和Foo2中都不是同一类型。所以我一定是用和你的代码不匹配的方式设置的。你能把Foo,Foo1,Foo2,Foo3和Bar的完整定义贴出来吗?
在您发布的示例中,您没有对Bar.var执行任何操作。问题是您需要对不同类型的Bar.var执行操作,而不是需要区分Foo1、Foo2和Foo3?

关于rust - 将具有相同泛型的相同结构的枚举匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57480977/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com