As a new user I was disappointed to learn rust macros can't replicate syntax of builtins because they can only take one argument set. In order for user-defined flow control to not be second rate compared to built-ins, it should be possible to take a snippet using any of the built-in keywords:
while true {
....
}
and to add a !
after the language keyword:
while! true {
....
}
and have it be possible to define while!
such that both snippets compile and have the same behavior . Currently macro_rules
can't express the above because of true
appearing before the braces. This would go for all of the major keywords, for
, fn
, etc. I understand that rust macros are not based on text substitution, I'm not proposing that while!
would simply be text substituted with while
, but rather that there would be some way to express that the macro can be followed by an expression and then a pair of braces containing statements.
I ran into this trying to port the C++ Catch test framework to rust as an exercise. It features a fairly novel control flow feature, where you write something like:
TEST_CASE("foo") {
// code common to all tests goes here
// declare some variables, init some things
SECTION("a") {
SECTION("x") {
...
}
SECTION("y") {
...
}
}
SECTION("b") {
}
SECTION("c") {
SECTION("z") {
...
}
SECTION("w") {
...
}
}
}
And it then runs the test in a loop, where each iteration runs different sections:
- Iteration 1: a, x
- Iteration 2: a, y
- Iteration 3: b
- Iteration 4: c, z
- Iteration 5: c, w
So each iteration is going to a different leaf in the section "tree." This makes tests much more succinct to write and avoids the need to define test fixtures entirely (all the code the setup that normally goes in a fixture just goes in the test case above all the sections).
So far I have failed to be able to replicate the syntax or something close with macro_rules. Either one of:
test_case! "mytestname" {
section! "a" {
}
}
Or:
test_case!("mytestname") {
section!("a") {
}
}
would be great, but neither are expressible syntax. Catch is able to get away with it because C++ just uses text substitution, and it's disappointing that Rust's much more sophisticated system can't (I think?) do the same. The closest I can get is:
test_case! {
"this is kind of like a docstring in Python";
// now everything else is real code
section! {
"a";
// now the code
}
}
Which I think is less clear, it's not obvious to a newcomer that the first line is special. Not being able to express this sort of thing would also prevent being able to write any loop construct as nice looking as for
or while
.
Are there any plans to address something like this? Am I mistaken and there is already a way to do this?