如何从字符串生成元组?

How to generate tuples from strings?

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

// 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 和 return 元组? 你可以try here

元组是一个异构集合;每个元素可能属于不同的类型。在您的示例中,它们 不同的类型,因此每个 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,) 等。而不是 ()(1)(1, 2)(1, 2, 3)——关键区别在于单元素元组可以工作(尽管你仍然会遗憾地写成 read_tuple!(lines, (T))).