如何从字符串生成元组?

时间:2015-04-14 03:33:31

标签: rust

我正在编写一个宏来逐行解析一些结构化文本到元组中。大多数部分现在都可以工作,但是我坚持通过从向量中提取/转换字符串来形成元组。

// Reading Tuple from a line
// Example : read_tuple( "1 ab 3".lines()
//                      ,(i32, String, i32))
//  Expected :  (1, "ab", 3)
// Note:: you can note use str
macro_rules! read_tuple {
      (
        $lines :ident , ( $( $t :ty ),* )
      )
        => {{
            let l = ($lines).next().unwrap();
            let  ws = l.trim().split(" ").collect::<Vec<_>>();
            let  s : ( $($t),*  ) = (
                // for w in ws {
                //     let p =  w.parse().unwrap();
                //   ( p) ,
                // }
                ws[0].parse().unwrap(),
                ws[1].parse().unwrap(),
                //...
                ws[2].parse().unwrap(),
                // Or any way to automatically generate these statments?
                );
            s
        }}
}

fn main() {
    let mut _x = "1 ab 3".lines();
    let a  = read_tuple!( _x, (i32, String, i32));

    print!("{:?}",a);
}

如何遍历ws并返回此宏中的元组? 你可以try here

1 个答案:

答案 0 :(得分:3)

元组是异构集合;每个元素可以是不同的类型。在您的示例中,它们的不同类型,因此每个parse方法都需要生成不同的类型。因此,纯粹的运行时迭代是正确的;你确实需要扩展所有ws[N].parse().unwrap()个语句。

遗憾的是,目前还没有任何方法可以写出$(…)*的当前迭代(尽管可以使用编译器插件进行模拟)。但是,有一种方法可以解决这个问题:混合运行和编译时迭代。我们使用迭代器来提取字符串,并使用宏迭代扩展(确保在$t中提到$(…),以便它知道要重复的内容)来生成相同行的正确数量。这也意味着我们可以避免使用中间向量,因为我们直接使用迭代器,所以我们全面赢了。

macro_rules! read_tuple {
    (
        $lines:ident, ($($t:ty),*)
    ) => {{
        let l = $lines.next().unwrap();
        let mut ws = l.trim().split(" ");
        (
            $(ws.next().unwrap().parse::<$t>().unwrap(),)*
        )
    }}
}

需要注意的一件小事是我如何将),*更改为,)*;这意味着您将获得()(1,)(1, 2,)(1, 2, 3,)和&amp; c。代替()(1)(1, 2)(1, 2, 3) - 关键区别在于单元素元组将起作用(尽管你仍然遗憾地写{{1} }})。