Tricky macro problem: Accept a sequence of possibly empty items (e.g. 1,2,,3) AND handle trailing commas properly
โ Rust ๐ 2025-10-21 ๐ค surdeus ๐๏ธ 3Hi,
In the library that I am working on, I would like to store sequences of sequences of things in compactly in memory by prepending each subsequence with its length. (In reality the things are symbols, and I use a union type for the element, and everything is properly encapsulated, but for simplicity integers will do here.)
So, for example, in the program below, the macro invocation seq_of_seqs![-1 -2, , -3] evaluates to
[
2, // Number of elements in first subsequence
-1, // First element of first subsequence
-2, // Second element of first subsequence
0, // Number of elements in second subsequence
1, // Number of elements in third subsequence
-3, // First and only element of third subsequence
]
Here is the full code
// Based on
// https://veykril.github.io/tlborm/decl-macros/building-blocks/counting.html#bit-twiddling
#[doc(hidden)]
#[macro_export]
macro_rules! _count_exprs {
() => { 0 };
($single:expr) => { 1 };
($odd:expr, $($a:expr, $b:expr),*) => { ($crate::_count_exprs!($($a),*) << 1) | 1 };
($($a:expr, $even:expr),*) => { $crate::_count_exprs!($($a),*) << 1 };
}
#[macro_export]
macro_rules! seq_of_seqs {
() => {{
[0; 0]
}};
($($($number:literal )*),* ) => {{
[
$(
$crate::_count_exprs!($($number),*)
$(, $number )*
),*
]
}};
}
fn main() {
dbg!(seq_of_seqs![-1 -2, , -3]);
}
This works, but the problem is that in accordance with Rust conventions, I would like to ignore trailing commas. I.e. I would like seq_of_seqs![-1 -2, , -3,] to evaluate to the same thing as above, but since I also need to support empty subsequences, seq_of_seqs![-1 -2, , -3,,] should evaluate to
[
2, // Number of elements in first subsequence
-1, // First element of first subsequence
-2, // Second element of first subsequence
0, // Number of elements in second subsequence
1, // Number of elements in third subsequence
-3, // First and only element of third subsequence
0, // Number of elements in fourth subsequence
]
Note that this is conceptually coherent. (Incidentally, I discovered that this is how JavsScript handles array literals.)
I know how to either
-
accept empty subsequences without handling trailing commas properly (thatโs the example above),
-
or accept trailing commas when no empty subsequences are allowed.
But despite a lot of trying and searching, I have not found a solution to have both. Itโs probably not helpful if I list all the things that I have tried (like explicitly matching sequences of commas with nothing in-between), because none of them have worked.
I would be grateful for any ideas or suggestions.
2 posts - 2 participants
๐ท๏ธ Rust_feed