如何在生锈中访问复杂枚举类型的元素?

时间:2014-03-08 05:59:46

标签: 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)
}

我这里有一个复杂的枚举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 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

我可能只是缺少你需要的具体语法,但是我不能为我的生活找到它...

修改:删除=&gt;这个例子的行动因为它似乎让每个人都感到困惑。阅读问题的人!我想从已经存在的枚举中的中获取子值,而不是匹配()枚举并执行println!

4 个答案:

答案 0 :(得分:4)

非常简单:

let x = A(EventOne { x: 0.1, y: 0.1 }, ~"Hello");
match 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");
match 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字段,而另一个字段是隐式可复制的,因为它包含隐式可复制数据。

答案 1 :(得分:0)

您需要使用match,就像在最后一个示例中所做的那样。你在那里得到的错误是由于使用了trace!()(那是什么?我的Rust没有它),它的返回类型为IoResult<()>(这是{{1}的typedef但是Rust希望你的表达式有Result<(),std::io::IoError>类型。

答案 2 :(得分:0)

如果有人提出,我会接受另一个更好的解决方案,但是这样做的方法是:

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);
}

答案 3 :(得分:0)

use std::rand;
use std::rand::Rng;

#[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)
}

#[deriving(Eq, Show)]
enum Event { EventOne, EventTwo }

fn main() {
    let mut rng = rand::rng();

    let z:ComplexEvent =
        if rng.gen() {
            A(EventOne { x: 0.1, y: 0.1 }, ~"☺")
        } else {
            B(EventTwo { x: 100, y: 200 }, ~"☹")
        };

    match z {
        A(e, _) => println!("{}", e),
        B(e, _) => println!("{}", e)
    }
}