I previously used C/C++ and recently started using Rust. I'm experiencing difficulties on writing simple macro_rules!
to automatically implement some helper methods.
Originally, I had Scanner
struct, which scans data from stdio
and converts them into a given type.
struct Scanner {
buffer: Vec<String>
}
impl Scanner {
fn next<T: std::str::FromStr>(&mut self) -> T { /* tldr */ }
}
After that, I tried to implement a helper macro to implement two methods which return T
and Vec<T>
respectively.
// It doesn't work 😢
macro_rules! scanner_shortcut {
($scan_type:ident, $single_scan_ident:ident, &multi_scan_ident:ident) => {
impl Scanner {
fn $single_scan_ident(&mut self) -> $scan_type {
self.next()
}
fn $multi_scan_ident(&mut self, n: usize) -> Vec<$scan_type> {
(0..n).map(|_| self.next()).collect()
}
}
};
}
scanner_shortcut!(i32, scan_i32, scan_i32s);
scanner_shortcut!(i64, scan_i64, scan_i64s);
However, I got the following error message: no rules expected this token in macro call
error: no rules expected the token `scan_i32s`
--> src/bin/playground.rs:36:34
|
23 | macro_rules! scanner_shortcut {
| ----------------------------- when calling this macro
...
36 | scanner_shortcut!(i32, scan_i32, scan_i32s);
| ^^^^^^^^^ no rules expected this token in macro call
error: no rules expected the token `scan_i64s`
--> src/bin/playground.rs:37:34
|
23 | macro_rules! scanner_shortcut {
| ----------------------------- when calling this macro
...
37 | scanner_shortcut!(i64, scan_i64, scan_i64s);
| ^^^^^^^^^ no rules expected this token in macro call
I struggled to get rid of this problem, and I found that when I remove &multi_scan_ident:ident
and the corresponding method declaration, it works well!
// It works well... 🧐
macro_rules! scanner_shortcut {
($scan_type:ident, $single_scan_ident:ident) => {
impl Scanner {
fn $single_scan_ident(&mut self) -> $scan_type {
self.next()
}
}
};
}
scanner_shortcut!(i32, scan_i32);
scanner_shortcut!(i64, scan_i64);
I guess the first code has some syntactic problems with the macro definition because the second version works well, but I couldn't figure out the exact reason. What makes this difference?
Any help will be appreciated!
You have a syntax error:
&multi_scan_ident:ident
This should be:
$multi_scan_ident:ident