如何访问rust中复杂枚举类型的元素?

如何访问rust中复杂枚举类型的元素?,rust,Rust,例如,考虑: #[deriving(Eq, Show)] struct EventOne { x: f64, y: f64 } #[deriving(Eq, Show)] struct EventTwo { x: int, y: int } #[deriving(Eq, Show)] enum ComplexEvent { A(EventOne, ~str), B(EventTwo, ~str) } 这里有一个复杂的enum ComplexEvent,可以是a,也可

例如,考虑:

#[deriving(Eq, Show)]
struct EventOne {
  x: f64,
  y: f64
}

#[deriving(Eq, Show)]
struct EventTwo {
  x: int,
  y: int
}

#[deriving(Eq, Show)]
enum ComplexEvent {
  A(EventOne, ~str),
  B(EventTwo, ~str)
}
这里有一个复杂的enum ComplexEvent,可以是a,也可以是B

我希望能够做到以下几点:

let x = A(EventOne { x: 0.1, y: 0.1}, ~"Hello");
let z = x.EventOne;
…但这会导致错误:

error: attempted access of field `EventOne` on type `union::ComplexEvent`, but no field with that name was found
let z = x.EventOne;
嗯。。。好的,作为一个数组

error: cannot index a value of type `union::ComplexEvent`
let z = x[0];
好吧,为了确保类型安全,也许你需要使用match

match x {
  A(_, _) => ???,
  B(_, _) => ???
}

...

union.rs:28:3: 31:4 error: mismatched types: expected `()` but found `std::result::Result<(),std::io::IoError>` (expected () but found enum std::result::Result)
union.rs:28   match x {
union.rs:29     A(_, _) => ???,
union.rs:30     B(_, _) => ???
union.rs:31   }
error: aborting due to previous error
匹配x{
A(,)=>???,
B(???
}
...
union.rs:28:3:31:4错误:不匹配的类型:应为`()`但找到` std::result::result`(应为()但找到enum std::result::result)
联盟。rs:28对x{
联合报:29A(,)=>???,
联合报:30B(,)=>???
联合报,rs:31}
错误:由于上一个错误而中止
我可能只是错过了让它工作所需的特定语法,但我无法用我的一生来理解它


编辑:删除示例上的=>操作,因为它似乎让每个人都感到困惑。读这个问题,伙计们!我想从已经存在的枚举中获取子值,而不是匹配()枚举并执行println

您需要使用
匹配
,就像您在最后一个示例中所做的那样。出现的错误是由于使用了
trace!()
(那是什么?我的Rust没有),它的返回类型为
IoResult
(这是
结果的typedef),但是Rust希望您的表达式的类型为
()

,您需要使用
匹配,就像您在最后一个示例中所做的那样。出现的错误是由于使用了
trace!()
(那是什么?我的Rust没有),它的返回类型为
IoResult
(这是
结果的typedef),但Rust希望您的表达式的类型非常简单:

让x=A(EventOne{x:0.1,y:0.1},~“Hello”);
匹配x{
A(EventOne{x,y},s)=>println!(“{},{},{},{}”,x,y,s),
B(EventTwo{x,y},s)=>println!(“{},{},{},{}”,x,y,s)
}
请注意,这样的匹配意味着您正在移出
~str
字段,因为它不是隐式可复制的,所以
x
将成为部分移动的值,您无法进一步使用。如果要在匹配后使用该值,可以通过引用绑定
s

let x=B(EventTwo{x:1,y:2},~“World”);
匹配x{
A(EventOne{x,y},ref s)=>println!(“{},{},{},{}”,x,y,*s),
B(EventTwo{x,y},ref s)=>println!(“{},{},{},{}”,x,y,*s)
}
在本例中,
s
具有类型
&~str
,因此您必须取消对它的引用以打印它。之后您将能够使用
x
,因为您没有将
~str
字段移出,而另一个字段是隐式可复制的,因为它包含隐式可复制的数据。

非常简单:

让x=A(EventOne{x:0.1,y:0.1},~“Hello”);
匹配x{
A(EventOne{x,y},s)=>println!(“{},{},{},{}”,x,y,s),
B(EventTwo{x,y},s)=>println!(“{},{},{},{}”,x,y,s)
}
请注意,这样的匹配意味着您正在移出
~str
字段,因为它不是隐式可复制的,所以
x
将成为部分移动的值,您无法进一步使用。如果要在匹配后使用该值,可以通过引用绑定
s

let x=B(EventTwo{x:1,y:2},~“World”);
匹配x{
A(EventOne{x,y},ref s)=>println!(“{},{},{},{}”,x,y,*s),
B(EventTwo{x,y},ref s)=>println!(“{},{},{},{}”,x,y,*s)
}

在本例中,
s
具有类型
&~str
,因此您必须取消对它的引用以打印它。之后,您将能够使用
x
,因为您没有将
~str
字段移出,而另一个字段是隐式可复制的,因为它包含隐式可复制的数据。

如果出现了另一个更好的解决方案,我会接受,但方法是:

macro_rules! trace(
  ($($arg:tt)*) => (
    { ::std::io::stdout().write_line(format_args!(::std::fmt::format, $($arg)*)); }
  );
)

#[deriving(Eq, Show)]
struct EventOne {
  x: f64,
  y: f64
}

#[deriving(Eq, Show)]
struct EventTwo {
  x: int,
  y: int
}

#[deriving(Eq, Show)]
enum ComplexEvent {
  A(EventOne, ~str),
  B(EventTwo, ~str)
}

#[test]
fn test_lifetime_scope() {
  let x = A(EventOne { x: 0.1, y: 0.1}, ~"Hello");
  let y = B(EventTwo { x: 1, y: 2}, ~"Hello2");
  let mut z:&EventOne = &EventOne { x: 0.0, y: 0.0 };

  match x {
    A(ref a, _) => z = a,
    B(b, _) => trace!("{}", b)
  }

  trace!("Accessed values: {}", z);
}

如果有更好的解决方案,我会接受,但方法是:

macro_rules! trace(
  ($($arg:tt)*) => (
    { ::std::io::stdout().write_line(format_args!(::std::fmt::format, $($arg)*)); }
  );
)

#[deriving(Eq, Show)]
struct EventOne {
  x: f64,
  y: f64
}

#[deriving(Eq, Show)]
struct EventTwo {
  x: int,
  y: int
}

#[deriving(Eq, Show)]
enum ComplexEvent {
  A(EventOne, ~str),
  B(EventTwo, ~str)
}

#[test]
fn test_lifetime_scope() {
  let x = A(EventOne { x: 0.1, y: 0.1}, ~"Hello");
  let y = B(EventTwo { x: 1, y: 2}, ~"Hello2");
  let mut z:&EventOne = &EventOne { x: 0.0, y: 0.0 };

  match x {
    A(ref a, _) => z = a,
    B(b, _) => trace!("{}", b)
  }

  trace!("Accessed values: {}", z);
}
使用std::rand;
使用std::rand::Rng;
#[推导(等式,显示)]
结构事件{
x:f64,
y:f64
}
#[推导(等式,显示)]
结构事件二{
x:int,
y:int
}
#[推导(等式,显示)]
枚举复合事件{
A(EventOne,~str),
B(事件二,~str)
}
#[推导(等式,显示)]
枚举事件{EventOne,EventTwo}
fn main(){
让mut rng=rand::rng();
让z:ComplexEvent=
如果rng.gen(){
A(EventOne{x:0.1,y:0.1},~”☺")
}否则{
B(EventTwo{x:100,y:200},~”☹")
};
匹配z{
A(e,)=>println!(“{}”,e),
B(e,)=>println!(“{}”,e)
}
}
使用std::rand;
使用std::rand::Rng;
#[推导(等式,显示)]
结构事件{
x:f64,
y:f64
}
#[推导(等式,显示)]
结构事件二{
x:int,
y:int
}
#[推导(等式,显示)]
枚举复合事件{
A(EventOne,~str),
B(事件二,~str)
}
#[推导(等式,显示)]
枚举事件{EventOne,EventTwo}
fn main(){
让mut rng=rand::rng();
让z:ComplexEvent=
如果rng.gen(){
A(EventOne{x:0.1,y:0.1},~”☺")
}否则{
B(EventTwo{x:100,y:200},~”☹")
};
匹配z{
A(e,)=>println!(“{}”,e),
B(e,)=>println!(“{}”,e)
}
}

+1我只会将初始
x
变量的名称更改为
z
,这样它就不会被相同名称的内部变量隐藏,只是为了弄清楚。@pepper_chico,你是对的,但是,我注意到从外部范围重写变量在Rust中是惯用的。
x
不应该在match中使用arms,所以可以安全地保持原样。+1我只会将初始
x
变量的名称更改为
z
,这样它就不会被相同名称的内部变量隐藏起来,只是为了让事情更清楚。@pepper_chico,你是对的,但是,我注意到从外部范围重写变量在Rust中是惯用的。
x
不是应该是我用的