如何从字符串生成元组?
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))
).
我正在编写一个宏来将一些结构化文本逐行解析为元组。大多数部分现在都可以工作,但我坚持通过 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))
).